SetSelected () funciona buggy con ListView

Estoy tratando de hacer clic en los elementos de ListView para cambiar de fondo. Pero no me parece realmente posible. Hay un montón de puestos con ejemplos de hacerlo, pero ninguno de ellos funciona de manera fiable. Como entendí – de alguna manera está relacionado con el "reciclaje".

Llamo view.setSelected () en OnItemClickListener del adaptador y aplica perfectamente otro fondo al artículo seleccionado según mi configuración. Pero cuando selecciono el elemento que hace que ListView carezca de espacio (no es importante cómo exactamente) y una scollbar aparece (o desaparece) dentro de ListView – android se olvida de mi selección y se aplica el estilo predeterminado. El mismo error ocurre al girar la pantalla: el elemento se anula la selección. Así que creo que "deselection" se produce mientras getView () del adaptador se está llamando.

Es interesante que mi evento onClick cause el envío de una solicitud json a un servicio en segundo plano y la recepción y decodificación de una respuesta json, por lo que toma algún tiempo entre un clic de artículo y el cambio de contenido de la actividad. Así es como se ve:

  1. Hago clic en un elemento ListView. Cambia de fondo a "color seleccionado".
  2. Pocos momentos estoy esperando.
  3. El contenido de la actividad está cambiando según una respuesta de servicio. Una barra de desplazamiento aparece dentro de ListView. El fondo del elemento cambia a "color predeterminado" (el elemento está deseleccionado).

Al hacer clic en los elementos que no hacen que aparezca una barra de desplazamiento, funciona bien: los elementos seleccionados no se deseleccionan después de procesar la respuesta del servicio.

Intentar llamar a setSelected () dentro de getView () del adaptador no da ningún efecto en el error. El elemento aún está desactivado. Intenté fijar el fondo del artículo manualmente en getView () – y se hizo más interesante: los artículos que causan la apariencia de una barra de desplazamiento comenzaron a trabajar correctamente, pero los artículos que no causan apperance de la barra de desplazamiento (realmente significa que no causan GetView () llamando) dejó de funcionar!

Todo el código es bastante complejo, por lo que publicaré sólo algunos fragmentos importantes. Aquí está mi OnItemClickListener:

private AdapterView.OnItemClickListener onCategoryClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, final View view, final int position, long id) { categoriesAdapter.setSelectedPosition(position); view.setSelected(true); // More code here } }; 

Y aquí hay un fragmento del código de mi adaptador:

 private int selectedPosition; private boolean selectable = true; public void setSelectedPosition(int position) { this.selectedPosition = position; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView label = (TextView) View.inflate(context, textViewResourceId, null); label.setText(getName(values.get(position))); if(selectable) { label.setBackgroundResource(R.drawable.list_selector); if(position == selectedPosition) { label.setSelected(true); // This does not work. Why? label.setBackgroundColor( // This gives strange results context.getResources().getColor(R.color.list_item_selected_color)); } else { // Similar code here, but for deselecting items. } } return label; } 

Y aquí está mi selector:

 <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/list_item_default_color" android:state_selected="false" /> <item android:drawable="@color/list_item_selected_color" android:state_selected="true"/> </selector> 

Busqué mucho para saber cómo hacerlo funcionar, pero nada ayuda. Estas son algunas de las cosas que probé:

  • Running view.setSelected () dentro de view.post ()
  • Ejecutar list.setSelection () – ¿para qué sirve este método? ¡No hace nada!
  • Inicializar TextView más preciso, comprobando si convertView es nulo. Da malos, muy malos resultados – hace que los elementos ListView se mezclen (sin afectar en su estado de selección).
  • No utilice ViewHolder porque no tengo diseños complejos para el elemento, solo tengo un TextView simple.

Para API 11+:

1) Establecer la vista de lista a elección única:

 <ListView android:choiceMode="singleChoice" /> 

2) Establezca el fondo del elemento raíz de la disposición del elemento en su selector:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="@drawable/selector"> 

3) Cambiar android:state_selected a android:state_activated :

 <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/list_item_selected_color" android:state_activated="true"/> <item android:drawable="@color/list_item_default_color"/> </selector> 

4) Resalta el elemento usando listView.setItemChecked(index, true);

Nota: Para que quede claro con respecto a los estados de la vista, especialmente state_activated puede comprobar este post ; es interesante.

Me confundía un poco con los colores. Después de arreglar algunos errores tonto mi selección está trabajando confiable fijando el color de fondo directamente de OnItemClickListener y de getView:

Fijo OnItemClickListener:

 public void onItemClick(AdapterView<?> parent, final View view, final int position, long id) { categoriesAdapter.setSelectedPosition(position); for (int j = 0; j < parent.getChildCount(); j++) { parent.getChildAt(j).setSelected(false); parent.getChildAt(j).setBackgroundColor(getContext().getResources().getColor( R.color.list_item_default_color)); } view.setBackgroundColor(getContext().getResources().getColor( R.color.list_item_selected_color)); // More code here } 

Adaptador fijo:

 private Integer selectedPosition; public void setSelectedPosition(int position) { this.selectedPosition = position; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView label = (TextView) View.inflate(context, textViewResourceId, null); label.setText(getName(values.get(position))); if(selectedPosition != null) { if(position == selectedPosition) { label.setBackgroundColor(context.getResources() .getColor(R.color.list_item_selected_color)); } else { label.setBackgroundColor(context.getResources() .getColor(R.color.list_item_default_color)); } } return label; } 

Por lo tanto, una forma de hacerlo con <selector> no funciona porque android no puede cambiar de forma fiable el estado del widget. ¿Es correcto o alguien tiene " <selector> manera" de trabajo?

  • Problema con la imagen de 9 parches como fondo
  • Android Listview con hilandero y una casilla de verificación
  • Cómo desplazarse y desplazarse hasta el último en Appium
  • Cómo actualizar un CursorAdapter vinculado a listview cuando el número de elementos cambia?
  • En Android, ¿cómo lograr un efecto de snap en un listview respetando la aceleración causada por fling?
  • Android lista ver espacio extra al final cuando se desplaza
  • El adaptador personalizado de Android no funciona correctamente para la lista de chat
  • EditText con la lista de sugerencias a continuación
  • El efecto Ripple no va por encima de ImageView
  • Crash después de agregar pie de página a ListView
  • Haga clic en un elemento ListView cambia el estado de los elementos dentro del elemento?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.