Ответ 1
Установите clickable
, focusable
, focusableInTouchMode
в true
во всех элементах списка RecyclerView
".
Я использую RecyclerView
, как показано ниже:
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="320dp"
android:layout_height="match_parent"/>
и мой элемент списка:
<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>
подробнее см. эту часть android:background="@drawable/selector_medium_high"
это обычный селектор:
<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>
но когда я запускаю этот код, у меня нет изменений в цвете фона, когда я касаюсь строки....
Установите clickable
, focusable
, focusableInTouchMode
в true
во всех элементах списка RecyclerView
".
Добавить:
android:background="?android:attr/selectableItemBackground"
in item.xml
Добавление android:background="?android:attr/selectableItemBackground"
в my_list_item.xml
корневого макета, похоже, работает для меня (при условии, что вам нужен цвет выбора по умолчанию).
Также убедитесь, что корневой макет android:layout_width
равен match_parent
, а не wrap_content
, чтобы обеспечить выбор всей строки.
Если ничего из этого не работает для вас, как и не для меня, используйте этот код:
android:foreground="?android:attr/selectableItemBackground"
Трюк находится в атрибуте android:foreground
...
К сожалению, использование настраиваемых представлений для имитации выбора элементов не является хорошим решением, потому что:
notifyDataSetChanged
вызываетсяЯ написал класс базового адаптера, который автоматически обрабатывал выбор элементов с помощью RecyclerView. Просто извлеките из него свой адаптер и используйте доступные списки состояний с помощью state_selected, как и в режиме просмотра списка.
У меня есть Blog Post Here об этом, но вот код:
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);
}
});
}
}
}
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;
}
});
Добавьте этот атрибут ниже в свой элемент "my_list_item.xml" android:descendantFocusability="blocksDescendants"
Это работает для меня!
Вам нужно установить android:clickable="true"
в элементе xml, и если в вашем представлении есть несколько селекторов, вы должны установить android:duplicateParentState="true"
там тоже.
Thats работает на pre honeycomb apis.
Как многие другие ответили, единственный способ - объединить селекторы и новые классы для отслеживания выбора, но лучше делегировать этот расчет для адаптера. Библиотека FlexibleAdapter отслеживает выбор для вас, изменение конфигурации также совместимо.
Цвет фона с пульсацией теперь можно выполнить без части XML, но в коде для управления динамическими данными.
Наконец, вы можете использовать множество функций с одной и той же библиотекой, выбор - крошечная базовая функция, которую вы можете иметь.
Пожалуйста, ознакомьтесь с описанием, страницами Wiki и полным рабочим примером: https://github.com/davideas/FlexibleAdapter