android - AutoCompleteTextView onItemHaga clic en la posición o id del elemento usando HashMap
(1)
Soy nuevo en el desarrollo de Android y encontré un problema que encuentro difícil de resolver. Estoy intentando descubrir cómo usar un widget AutoCompleteTextView
correctamente. Quiero crear un AutoCompleteTextView
, usando datos XML de un servicio web. Me las arreglé para que funcione, pero definitivamente no estoy satisfecho con la salida.
Me gustaría poner un HashMap
con id => pares de nombres en AutoCompleteTextView
y obtener el id del elemento cliqueado. Cuando hago clic en el resultado del conjunto filtrado autocompletado, quiero llenar una lista debajo del cuadro de autocompletado, que también pude poner en práctica.
Hecho hasta ahora:
- autocompletar funciona bien para ArrayList simple, todos los datos filtrados son correctos
- El evento onItemClick se desencadena correctamente después de hacer clic
- parent.getItemAtPosition (position) devuelve la representación de cadena correcta del elemento cliqueado
El evento onItemClick (AdapterView parent, View v, int position, long id) no se comporta como me gustaría. ¿Cómo puedo averiguar la posición de la matriz no filtrada del elemento cliqueado? La posición del filtrado es la que no me interesa.
Mas preguntas:
- Cómo manejar HashMaps o colecciones en AutoCompleteTextView
- Cómo obtener el itemId correcto en el evento onItemClick
Hice una investigación muy extensa sobre este tema, pero no encontré ninguna información valiosa que respondiera mis preguntas.
Cómo manejar HashMaps o colecciones en AutoCompleteTextView
Puede configurar su propio adaptador personalizado. En su adaptador depende de usted dónde obtiene sus datos en una posición determinada.
Cómo obtener el itemId correcto en el evento onItemClick
En su adaptador personalizado, define un filtro, y ese filtro establece los elementos sugeridos. Tienes dos listas diferentes, una con los valores originales y otra con los elementos filtrados. Quiero decir algo como esto.
private class AutoCompleteItemAdapter extends ArrayAdapter<YourItemClass> implements Filterable {
private NameFilter mFilter;
List<YourItemClass> suggestions;
List<YourItemClass> mOriginalValues;
public AutoCompleteItemAdapter(Context context, int resource, List<YourItemClass> suggestions) {
super(context, resource, suggestions);
this.suggestions = suggestions;
this.mOriginalValues = suggestions;
}
public void updateData(List<YourItemClass> suggestions) {
mLock.lock();
try{
this.suggestions = suggestions;
this.mOriginalValues = suggestions;
finally{
mLock.unlock();
}
}
@Override
public int getCount() {
mLock.lock();
try {
return suggestions.size();
} finally {
mLock.unlock();
}
}
@Override
public YourItemClass getItem(int position) {
return mOriginalValues.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// draw your item here...
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new NameFilter();
}
return mFilter;
}
private class NameFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
mLock.lock();
try {
mOriginalValues = new ArrayList<YourItemClass>(suggestions);
} finally {
mLock.unlock();
}
}
if (prefix == null || prefix.length() == 0) {
mLock.lock();
try {
ArrayList<YourItemClass> list = new ArrayList<YourItemClass>(mOriginalValues);
results.values = list;
results.count = list.size();
} finally {
mLock.unlock();
}
} else {
String prefixString = prefix.toString().toLowerCase();
final List<YourItemClass> values = mOriginalValues;
final int count = values.size();
final ArrayList<YourItemClass> newValues = new ArrayList<YourItemClass>(count);
// FILTERING
//
// add your hits to the newValues collection
//
//
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mLock.lock();
try {
if (results == null || results.values == null) return;
suggestions = new ArrayList<YourItemClass>();
suggestions = (List<YourItemClass>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
} finally {
mLock.unlock();
}
}
}
}
Ahora bien, esto podría plantear algún problema de concurrencia, ya que como referencia, el adaptador podría solicitar el tamaño de la lista, y se eliminará un valor mayor, lo que podría causar problemas en la función getView. (fi .: Intentar dibujar 5 elementos con los datos subyacentes solo tiene 4, porque hicimos otro filtrado) Esta es la manera en que usamos nuestro AutoCompleteTextView
, y hasta ahora funciona muy bien, no hay problema. Acabo de mencionar que todavía estoy preocupado, y tengo la vaga sensación de que hay una mejor solución para esto.
En su oyente onClick, usa el valor devuelto (de la lista filtrada) como la clave en su mapa, y obtiene el valor asociado. Puede pensar que su lista utiliza un índice para HashMap
. Después de eso, puede usar su Map
para dibujar su artículo o para obtener sus propios datos.