在RecyclerView中选择项目

13

类似的问题已经被问过了,但是我没有找到任何一个可行的解决方法。

我想要实现的是,在RecyclerView中选择项目,更改该项目视图的背景,并存储所选项目的位置。

主要问题在于你有 onCreateViewHolder(在适配器中),onBindViewHolder(在适配器中)和 ViewHolder 构造函数,每个人都使用不同的方法。 现在,我甚至不知道把 onClickListener 放在哪里(在以前的项目中,我把它放在 ViewHolder 中),因为有人建议使用其他两种方法。

我的想法是将每个 ViewHolder(或视图)存储在列表中,这样我就可以引用每一行,并从那里更改背景。但是对我来说,这并没有起作用,因为当我尝试从三个地方之一(onCreateVH、onBindVH、VH类)添加到视图(或 ViewHolders)列表时,我的应用程序会因某些原因而崩溃(null pointer ex)。

有什么建议吗?在哪里以及如何实现?


请参考第一部分和第二部分。这是有关RecyclerView的绝佳教程。第二部分清晰地解释了如何实现具有选择项目、单击以及其他所有listview内容的RecyclerView。源代码也可以在Github上找到。希望这有所帮助。http://www.bignerdranch.com/blog/recyclerview-part-2-choice-modes/ - denvercoder9
让你的模型拥有一个布尔字段:选中/未选中,当你点击该项时切换其值并调用notifyItemChanged(int position),就这么简单。 - pskink
我已经让某些东西工作了,但是当我选择一个项目并向下滚动时,其他项目也会被选择(这些项目是选定项目的回收视图)。仍在寻找解决方法... - JoKr
其他项目被选中是因为视图被回收利用了。您必须在onViewRecycled中取消选择。但是,如果您实现适当的“仅选择一个”行为,则无需处理此问题。 - Ali Kazi
2个回答

14

创建全局变量来存储位置并在ViewHolder中处理点击监听。当项目被点击时,更改全局位置值,例如:

textView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        globalPosition=getAdapterPosition();
        notifyDataSetChanged();
    }
});

然后在 onBindViewHolder 中实现。

if(postion==globalPosition)
{
    //change color like
    textview.setTextColor(Color.RED);
}
else
{
    //revert back to regular color 
    textview.setTextColor(Color.WHITE);
}

通过这段代码,你所点击的项会变成红色,其他项则保持白色。

notifyDataSetChanged可以工作,但如果您有大量数据集,则重新绑定视图会影响性能。这是来自notifyDataSetChanged文档的说明:此事件未指定数据集更改的内容,强制任何观察者假定所有现有项目和结构可能不再有效。布局管理器将被强制完全重新绑定和重新布局所有可见视图。 - Ali Kazi

1

首先,你问在哪里放置onClickListener - 你应该将其放置在onBindViewHolder中。你也可以像下面这样在你的项目的ViewHolder类中附加一个onClickListener:

public class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View itemView) {
            super(itemView);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                }
            });
        }
    }

针对实现单选行为,这里提供的答案是有效的,但如果你有很多项并且每次都重新绑定所有视图,调用onNotifyDatasetChanged会影响性能。
denvercoder9提供的链接是一个好的教程,可以帮助理解如何设置RecyclerView,但我认为它使单选行为变得复杂。我将全面回答并提供所有必要的内容来使其正常工作。以下是我如何实现单选行为的方法:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    final YourItemViewHolder itemViewHolder = (YourItemViewHolder) holder;
    //This will remember which one was selected
    itemViewHolder.getItemSelectionIndicator()
            .setSelected(position == mSelectedPosition);
        itemViewHolder.getItemWrapperView()
            .setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d(mLogTag, "Tapped on " + position);
                    //This is the previous selection
                    notifyItemChanged(mSelectedPosition);
                    itemViewHolder.getItemSelectionIndicator().setSelected(true);
                    mSelectedPosition = position;
                    //This is the new selection
                    notifyItemChanged(position);
                }
            });

getItemSelectionIndicator()getItemWrapperView()是ViewHolder中的方法,它们从item布局返回特定的视图。ItemWrapperView可以是包装整个项的顶部Linear/RelativeLayout。在其上设置点击监听器将确保如果用户在项目视图中的任何地方轻击,则单击有效。

ItemSelectionIndicator可以是已设置状态列表可绘制背景的Linear或RelativeLayout。这意味着当它被设置为选定时,它会自动显示一个形状绘制以指示选择。当它被设置为未选定时,绘制将自动删除。这就是指示器视图的外观:

<RelativeLayout
        android:id="@+id/selection_indicator"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/selection_indicator_state_list"/>

这是位于res/drawable中的selection_indicator_state_list.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Selected background -->
    <item android:state_selected="true"
          android:drawable="@drawable/item_selection_shape"/>
    <!-- Unselected background -->
    <item android:state_selected="false"
        android:drawable="@color/transparent"/>
</selector>

这是res/drawable中的item_selection_shape.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    //22 is value of transparency, BDBDBD is the color
    <solid android:color="#22BDBDBD"/>
    <stroke android:width="2dp" android:color="@color/md_blue_600"/>
    <corners
        android:radius="3dp"/>
</shape>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接