-1

我需要在 android Recycler View 的每个条目中使用复选框选择一些项目。一旦我检查了位置 0 的复选框,滚动时也会自动检查每个第 9 个位置的复选框。

如何克服这一点?

//在我的适配器类中

   holder.approveCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            Logger.infoLog("Checked Position ==> "+position+" boolean ==> "+b);
        }
    });
4

4 回答 4

3

使用数组来保存项目的状态

在适配器中使用 Map 或SparseBooleanArray(类似于 map,但是是一个 int 和 boolean 的键值对)来存储我们项目列表中所有项目的状态,然后使用键和值进行比较切换选中状态时

在适配器中创建一个SparseBooleanArray

// sparse boolean array for checking the state of the items

    private SparseBooleanArray itemStateArray= new SparseBooleanArray();

然后在项目单击处理程序onClick()中使用 itemStateArray 中项目的状态在切换之前检查,这是一个示例

        @Override
        public void onClick(View v) {
            int adapterPosition = getAdapterPosition();
            if (!itemStateArray.get(adapterPosition, false)) {
                mCheckedTextView.setChecked(true);
                itemStateArray.put(adapterPosition, true);
            }
            else  {
                mCheckedTextView.setChecked(false);
                itemStateArray.put(adapterPosition, false);
            }
        }

另外,当视图被绑定时,使用稀疏布尔数组来设置检查状态

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    holder.bind(position);
}

@Override
public int getItemCount() {
    if (items == null) {
        return 0;
    }
    return items.size();
}

 void loadItems(List<Model> tournaments) {
    this.items = tournaments;
    notifyDataSetChanged();
}


class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    CheckedTextView mCheckedTextView;

    ViewHolder(View itemView) {
        super(itemView);
        mCheckedTextView = (CheckedTextView) itemView.findViewById(R.id.checked_text_view);
        itemView.setOnClickListener(this);
    }

    void bind(int position) {
        // use the sparse boolean array to check
        if (!itemStateArray.get(position, false)) {
            mCheckedTextView.setChecked(false);}
        else {
            mCheckedTextView.setChecked(true);
        }
    }
于 2019-01-18T12:35:04.040 回答
1

您正面临这个问题,因为RecyclerView使用 ViewHolder 模式,它重用子视图并减少内存消耗。

您可以点击此链接



也可以按照以下简单步骤操作。

1)在你的数据源中取一个布尔值,即你的数据/模型类的列表。
(这个布尔值将存储复选框的当前状态)

2) 在onClick复选框的情况下,切换渲染数据模型的布尔值并调用 notifyDataSetChanged。
(不要onCheckedChanged在这里使用)

3)在渲染放置条件时,是否根据该布尔值将复选框标记为选中或未选中。

于 2019-01-18T12:32:34.503 回答
1

如果您可以了解position匿名实现的内部,则意味着它是final. 就像那里的复选框侦听器一样。

Afinal position将导致数据和 UI 之间的差异,因为它不会被再次定义。此时应该有一个 lint in ononBindViewHolder方法,这比我的解释更好。

要以非决赛身份进入该职位,您可以使用:

holder.getAdapterPosition()

您不必担心持有人是最终的,因为持有人是行并且不会再次重新实例化。如果它被适配器回收,那么它就没有问题。

于 2019-01-18T12:33:44.560 回答
1

当我在 OnBindViewHolder 中分配checkedChange 侦听器时,我遇到了这个问题,因为回收时会多次调用它。对我有用的是在 viewHolder create 方法中定义回调和侦听器。

public class CheckBoxHolder : RecyclerView.ViewHolder
    {
        public TextView line, destination, twd;
        public ImageView icon;
        public LinearLayout lineParent;
        public CheckBox checkBox;
        public CheckBoxHolder(View view, Action<int, CompoundButton.CheckedChangeEventArgs> listener) : base(view)
        {
            checkBox = view.FindViewById<CheckBox>(Resource.Id.check_checkBox);

            twd = view.FindViewById<TextView>(Resource.Id.check_twd);
            destination = view.FindViewById<TextView>(Resource.Id.check_dest);
            line = view.FindViewById<TextView>(Resource.Id.check_line);
            lineParent = view.FindViewById<LinearLayout>(Resource.Id.check_line_parent);
            icon = view.FindViewById<ImageView>(Resource.Id.check_icon); 
            view.Click += (sender, e) => {
                checkBox.Checked = !checkBox.Checked;
            };
            checkBox.CheckedChange += (object sender, CompoundButton.CheckedChangeEventArgs e) => listener(base.Position, e);
        }
    }

这是来自 xamarin 的 C# 代码,但这个概念应该适用于您的问题。

于 2019-01-18T12:43:23.370 回答