RecyclerView 项中的背景选择器
Posted
技术标签:
【中文标题】RecyclerView 项中的背景选择器【英文标题】:Background Selector in RecyclerView Item 【发布时间】:2014-10-13 02:28:10 【问题描述】:我正在使用RecyclerView
,如下所示:
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_
android:layout_/>
还有我的列表项:
<LinearLayout android:layout_
android:layout_
android:background="@drawable/selector_medium_high">
<com.basf.suvinil.crie.ui.common.widget.CircleView
android:id="@+id/circle"
android:layout_
android:layout_/>
<TextView
android:id="@+id/label"
android:layout_
android:layout_
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>
但是当我运行这段代码时,当我触摸行时,背景颜色没有变化......
【问题讨论】:
不幸的是,使用可聚焦视图不是跟踪选择的好方法。检查我的答案以获得完整的解决方案。 【参考方案1】:在RecyclerView
“列表”的所有元素中将clickable
、focusable
、focusableInTouchMode
设置为true
。
【讨论】:
今天,RecyclerView 没有onItemClick。但是在可点击、可聚焦和可聚焦的InTouchMode中设置为true已经解决了这个问题:) 我不知道如何看到这种答案,但你帮我,我认为如果你只是删除第 2 步并在第 1 步中设置 true 而不是 false 就没有问题,它会没关系,答案是对的 “my_list_view”在哪里?在此示例中,我没有看到任何名为“my_list_view”的内容?令人困惑 他的意思是“列表”而不是“my_list_view” 为什么不使用 - android:background="?android:attr/selectableItemBackground" ?【参考方案2】:添加:
android:background="?android:attr/selectableItemBackground"
在item.xml
【讨论】:
但这会产生连锁反应。【参考方案3】:如果这些都不适合你,就像它不适合我一样,请使用以下代码:
android:foreground="?android:attr/selectableItemBackground"
诀窍在于android:foreground
属性...
【讨论】:
这样会有叠加实际内容的不良影响,只能在API 23之前的FrameLayout
使用(***.com/a/52411921/461982)【参考方案4】:
将android:background="?android:attr/selectableItemBackground"
添加到my_list_item.xml
的根布局 似乎对我有用(假设您想要默认选择颜色)。
还要确保根布局的android:layout_width
是match_parent
而不是wrap_content
,以确保整行都是可选的。
【讨论】:
使用android:background="?android:attr/selectableItemBackground"
时如何更改默认选择颜色?【参考方案5】:
很遗憾,使用可聚焦视图来模拟项目选择不是一个好的解决方案,因为:
调用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);
);
【讨论】:
谁是mRecyclerView?【参考方案6】: 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;
);
【讨论】:
但 Material Design 的答案很糟糕,因为这会破坏涟漪效应。【参考方案7】:在您的项目“my_list_item.xml”中添加以下属性android:descendantFocusability="blocksDescendants"
这对我有用!
【讨论】:
【参考方案8】:你需要在元素xml中设置android:clickable="true"
,如果你的视图里面的某个视图有更多的选择器,你需要设置android:duplicateParentState="true"
也有。
这适用于预蜂窝 API。
【讨论】:
【参考方案9】:正如许多其他人回答的那样,唯一的方法是结合选择器和新类来跟踪选择,但最好将此计算委托给适配器。 FlexibleAdapter 库为您跟踪选择,配置更改也兼容。
现在可以在没有 XML 部分的情况下使用带有波纹的背景颜色,而是在代码中管理动态数据。
最后,您可以在同一个库中使用许多功能,选择是您可以拥有的一个微小的基本功能。
请查看描述、Wiki 页面和完整的工作示例:https://github.com/davideas/FlexibleAdapter
【讨论】:
【参考方案10】:在您的设计或 xml 文件中只需放置以下行。
android:clickable="true"
android:focusable="true"
android:background="?android:attr/activatedBackgroundIndicator"
【讨论】:
以上是关于RecyclerView 项中的背景选择器的主要内容,如果未能解决你的问题,请参考以下文章