【问题标题】:In android, checking Checkbox in a RecyclerView, automatically checks some other checkboxes [duplicate]在android中,检查RecyclerView中的复选框,自动检查其他一些复选框[重复]
【发布时间】:2019-01-18 12:26:33
【问题描述】:

我需要使用 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);
        }
    });

【问题讨论】:

    标签: java android checkbox android-recyclerview


    【解决方案1】:

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

    在适配器中使用 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);
            }
        }
    

    【讨论】:

    • 最终的适配器会像this
    【解决方案2】:

    如果您可以在匿名实现中获得position,则意味着它是final。就像那里的复选框侦听器一样。

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

    你可以使用没有final的位置来访问这个位置:

    holder.getAdapterPosition()
    

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

    【讨论】:

      【解决方案3】:

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

      你可以关注这个link



      您可以按照这些简单的步骤进行操作。

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

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

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

      【讨论】:

        【解决方案4】:

        当我在 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# 代码,但这个概念应该适用于您的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多