如何在Android的RecyclerView中跟踪所选项目?

6
如何使用RecyclerView实现一致的项选择? 我理解了RecyclerView回收旧视图等整个思想。我的问题是,我有一个带有每个项目图标的项目列表,当单击项目时,图标会更改颜色。我成功地实现了所有这些,但我刚意识到,当我滚动列表时,其他项目的图标也会更改,并且当我滚动回到我单击的项目时,图标不再处于“单击颜色”中。
有人知道如何跟踪所选项目吗?我看到了一些叫做SparseBooleanArray的东西,但我不确定如何实现它。
这是我的适配器代码:
public class TableRVAdapter extends RecyclerView.Adapter<TableRVAdapter.TableHolder> {

    List<Tables> tableList;
    private SparseBooleanArray selectedItems;

    public TableRVAdapter(List<Tables> tableList)
    {
        this.tableList = tableList;
        selectedItems = new SparseBooleanArray();
       // setHasStableIds(true);
    }
    class TableHolder extends RecyclerView.ViewHolder
    {
        TextView tableTV;
        CardView tableCV;
        View circle;
        View parentView;
        TableHolder(final View itemView)
        {
            super(itemView);
            tableTV = (TextView)itemView.findViewById(R.id.tableTV);
            tableCV = (CardView)itemView.findViewById(R.id.tableCV);
            circle = itemView.findViewById(R.id.statusCircle);
            itemView.setClickable(true);
            parentView = itemView;

            tableCV.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                     circle.setBackgroundResource(R.drawable.circle);

                }
            });
        }
        /*
        @Override
        public void onClick(View view) {
            if (selectedItems.get(getAdapterPosition(), false)) {
                tableCV.setSelected(false);
                circle.setBackgroundResource(R.drawable.circle2);
            }
            else {
                selectedItems.put(getAdapterPosition(), true);
                tableCV.setSelected(true);
                circle.setBackgroundResource(R.drawable.circle);
            }

        }*/
    }

    @Override
    public TableHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.table_item,parent,false);
        TableHolder tableHolder = new TableHolder(view);
        return tableHolder;
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView)
    {
        super.onAttachedToRecyclerView(recyclerView);
    }


    @Override
    public void onBindViewHolder(TableHolder holder, int position) {
        holder.tableTV.setText(tableList.get(position).getTableNumber());

    }

    /**
     * Returns the total number of items in the data set hold by the adapter.
     *
     * @return The total number of items in this adapter.
     */
    @Override
    public int getItemCount() {
        return tableList.size();
    }

}
3个回答

4

我知道这个问题已经有答案了,但是有人可能会发现这个答案更加有用和易懂。

在Recycler View中有一个有用的方法叫做onViewRecycled

这可以帮助你摆脱按下状态。当在Recycler View中使用图片/可绘制对象时,如果某些元素不使用可绘制对象,那么预览Recycler View的绘制图像将存在,并且它会使所有数据看起来都是错误的,就像你的选择视图一样。

为了更简单地实现这一点,您可以使用此方法清除绘制的图像以重置其值。

例如,您将选定元素的背景标记为绿色,并且一些视图包含图像(注意:只有一些元素),则可以使用以下方法:

@Override
        public void onViewRecycled(MyViewHolder holder) {
            super.onViewRecycled(holder);

            // Set ImageView's Drawable as transperent
            holder.myImageView.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), android.R.color.transparent));

            // Set background color as transperent
            holder.bgContainer.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), android.R.color.transparent));

        }

现在,您可以使用recycler view的onClick方法来管理一个整数ArrayList,其中包含所选元素的id/位置。

使用onBindViewHolder(MyViewHolder myViewHolder, int position),您可以正常填充数据。要设置背景,只需检查id/位置是否在ArrayList中(如果为true,则将背景颜色设置为绿色,否则保持原样。由于它将由onViewRecylcer方法管理,并且即使未选择其他滚动项的绿色背景也不会受到影响)。

希望这能帮助某些人,使带有选择的recyler view更加容易。


3

RecyclerView.adapter有两个重要功能需要重写:

onCreateViewHolder(parent, viewType)
onBindVIewHolder(viewholder, position)

第一个函数用于填充将在 RecyclerView 中使用的视图,第二个函数用于将您拥有的数据绑定到该视图上,并因此在视图上设置正确的视图状态。
RecyclerView 本身仅会填充一定数量的视图,然后开始重复使用已经填充的视图(因此称为 RecyclerView)。因此,您需要在 onBindViewholder() 中为每个项目设置正确的状态,并在该位置使用集合中的项目来设置正确的视图状态。对于您的示例:根据对象中的布尔值(例如:isPressed)更改图标的颜色。

非常感谢您!还有,感谢您解释了onBindViewHolder的用途,我在阅读您的帖子后成功解决了问题。再次感谢! - spongyboss

1
你需要像这样保存实例。
if (isPressed) {
    icon.setCustomIcon();
} else {
    icon.setDefaultIcon();    
}

如果您有一个自定义对象需要一个布尔值isPressed或类似的东西,这应该可以工作。

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