single seleccion recyclerview multiple item android selector android-recyclerview

seleccion - selectable recyclerview android



Selector de fondo en RecyclerVer artículo (9)

Estoy usando el RecyclerView como a continuación:

<android.support.v7.widget.RecyclerView android:id="@+id/list" android:layout_width="320dp" android:layout_height="match_parent"/>

y mi elemento de la lista:

<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/selector_medium_high"> <com.basf.suvinil.crie.ui.common.widget.CircleView android:id="@+id/circle" android:layout_width="22dp" android:layout_height="22dp"/> <TextView android:id="@+id/label" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="57.5dp"/> </LinearLayout>

ver en detalle esta parte de android:background="@drawable/selector_medium_high" es un selector normal:

<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/background_high" android:state_activated="true"/> <item android:drawable="@color/background_high" android:state_pressed="true"/> <item android:drawable="@color/background_high" android:state_checked="true"/> <item android:drawable="@color/background_high" android:state_focused="true"/> <item android:drawable="@color/background_medium"/> </selector>

pero cuando ejecuto este código, no tengo cambios en el color de fondo cuando toco la fila ...


Agregar android:background="?android:attr/selectableItemBackground" al diseño de raíz de my_list_item.xml parece funcionar para mí (suponiendo que desee el color de selección predeterminado).

También asegúrese de que el diseño de la raíz de android:layout_width sea match_parent lugar de wrap_content para garantizar que toda la fila sea seleccionable.


Agregar:

android:background="?android:attr/selectableItemBackground"

en item.xml


Agregue este atributo a continuación en su artículo "my_list_item.xml"
android:descendantFocusability="blocksDescendants" Esto funciona para mí!


Como muchos otros respondieron, la única forma es combinar selectores y nuevas clases para realizar un seguimiento de la selección, pero es mejor delegar este cálculo en el adaptador. La biblioteca FlexibleAdapter realiza un seguimiento de las selecciones, el cambio de configuración también es compatible.

El color de fondo con rizado ahora se puede hacer sin parte XML, pero en el código para administrar datos dinámicos.

Finalmente, puede usar muchas características con la misma biblioteca, la selección es una pequeña característica básica que puede tener.

Por favor, eche un vistazo a la descripción, las páginas Wiki y el ejemplo de trabajo completo: https://github.com/davideas/FlexibleAdapter


Desgraciadamente, utilizar vistas enfocables para simular la selección de elementos no es una buena solución porque:

  • El foco se pierde cuando se llama a notifyDataSetChanged
  • El enfoque es problemático cuando las vistas de los niños son enfocables

Escribí una clase de adaptador base para manejar automáticamente la selección de elementos con un RecyclerView. Simplemente obtenga su adaptador y use listas de estado dibujables con state_selected, como lo haría con una vista de lista.

Tengo una publicación en el blog sobre esto, pero aquí está el código:

public abstract class TrackSelectionAdapter<VH extends TrackSelectionAdapter.ViewHolder> extends RecyclerView.Adapter<VH> { // Start with first item selected private int focusedItem = 0; @Override public void onAttachedToRecyclerView(final RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); // Handle key up and key down and attempt to move selection recyclerView.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { RecyclerView.LayoutManager lm = recyclerView.getLayoutManager(); // Return false if scrolled to the bounds and allow focus to move off the list if (event.getAction() == KeyEvent.ACTION_DOWN) { if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { return tryMoveSelection(lm, 1); } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { return tryMoveSelection(lm, -1); } } return false; } }); } private boolean tryMoveSelection(RecyclerView.LayoutManager lm, int direction) { int tryFocusItem = focusedItem + direction; // If still within valid bounds, move the selection, notify to redraw, and scroll if (tryFocusItem >= 0 && tryFocusItem < getItemCount()) { notifyItemChanged(focusedItem); focusedItem = tryFocusItem; notifyItemChanged(focusedItem); lm.scrollToPosition(focusedItem); return true; } return false; } @Override public void onBindViewHolder(VH viewHolder, int i) { // Set selected state; use a state list drawable to style the view viewHolder.itemView.setSelected(focusedItem == i); } public class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(View itemView) { super(itemView); // Handle item click and set the selection itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Redraw the old selection and the new notifyItemChanged(focusedItem); focusedItem = mRecyclerView.getChildPosition(v); notifyItemChanged(focusedItem); } }); } } }


Establezca clickable focusable , focusableInTouchMode y focusableInTouchMode en true en todos los elementos de la "lista" de RecyclerView .


Necesitas configurar android:clickable="true" en el elemento xml, y si tienes más selectores en alguna vista dentro de tu vista, necesitas configurar android:duplicateParentState="true" allí también. Eso funciona en apis previas al panal.


Si nada de esto funciona para usted, como no lo hizo para mí, use este código:

android:foreground="?android:attr/selectableItemBackground"

El truco está en android:foreground atributo de android:foreground ...


viewHolder.mRlPrince.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction()==MotionEvent.ACTION_DOWN){ viewHolder.mRlPrince.setBackgroundColor(Color.parseColor("#f8f8f8")); }if (event.getAction()==MotionEvent.ACTION_UP){ viewHolder.mRlPrince.setBackgroundColor(Color.WHITE); } return false; } });