【问题标题】:Duplication in Checkbox selection in RecyclerViewRecyclerView中复选框选择中的重复
【发布时间】:2017-10-26 09:43:55
【问题描述】:

下面是我的代码。

holder.followDiseaseCheckBox.setOnClickListener(new View.OnClickListener() {
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onClick(View view) {

            if (holder.followDiseaseCheckBox.isChecked()) {

                holder.followDiseaseCheckBox.setChecked(true);

                checkBoxClicked++;
                holder.followDiseaseCheckBox.setChecked(true);
                // for Follow.
                if (isFollowOrUnFollow.equals("FOLLOW")) {

                    ((FollowActivity) context).diseaseListFromAdapter.add(String.valueOf(diseaseMap.get("id")));
                    ((FollowActivity) context).setFollowButton(true);

                }
                // for Unfollow.
                else if (isFollowOrUnFollow.equals("UN_FOLLOW")) {

                    ((FollowTwoActivity) context).unFollowedDiseaseListFromAdapter.add(String.valueOf(diseaseMap.get("id")));
                    ((FollowTwoActivity) context).setUnFollowDiseaseButton(true);
                }


            } else {

                holder.followDiseaseCheckBox.setChecked(false);

                checkBoxClicked--;
                holder.followDiseaseCheckBox.setChecked(false);
                // for Follow.
                if (isFollowOrUnFollow.equals("FOLLOW")) {
                    ((FollowActivity) context).diseaseListFromAdapter.remove(String.valueOf(diseaseMap.get("id")));
                }
                // for Unfollow.
                else if (isFollowOrUnFollow.equals("UN_FOLLOW")) {
                    ((FollowTwoActivity) context).unFollowedDiseaseListFromAdapter.remove(String.valueOf(diseaseMap.get("id")));
                }

                if (checkBoxClicked == 0) {

                    // for Follow.
                    if (isFollowOrUnFollow.equals("FOLLOW")) {
                        ((FollowActivity) context).setFollowButton(false);
                        ((FollowActivity) context).diseaseListFromAdapter.clear();
                    }
                    // for Unfollow.
                    else if (isFollowOrUnFollow.equals("UN_FOLLOW")) {

                        ((FollowTwoActivity) context).setUnFollowDiseaseButton(false);
                        ((FollowTwoActivity) context).unFollowedDiseaseListFromAdapter.clear();
                    }
                }
            }

        }
    });

问题是当我选择一个checkBox 包括checkBox 时,RecyclerView 中的其他一些checkBox 会被选中。但是,当我签入 adapter 时,项目已正确添加,但 checkBox 选择被重复。

例如:如果我检查了第一项 checkBox 并向下滚动第 16 项 checkBox 也将被检查。取消选中 checkBox 也将取消选中第一项。

【问题讨论】:

    标签: android checkbox android-recyclerview


    【解决方案1】:

    回收器视图回收 OnBindViewHolder 中的视图。 因此,当单击项目时,它会反映在其他一些位置。 创建一个全局 SparseBooleanArray 来存储点击位置。

    private final SparseBooleanArray array=new SparseBooleanArray();
    

    然后在最终视图中添加 clickListener 和 onClick 存储被点击项目的位置。

    public class ViewHolder extends RecyclerView.ViewHolder {
        public YOURVIEW view;
        public ViewHolder(View v) {
            super(v);
            view = (YOURVIEW) v.findViewById(R.id.YOURVIEWID);
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    array.put(getAdapterPosition(),true);
                    notifyDataSetChanged();
                }
            });
        }
    }
    

    在 OnBindViewHolder 里面,

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        if(array.get(position)){
            holder.followDiseaseCheckBox.setChecked(true);
        }else{
            holder.followDiseaseCheckBox.setChecked(false);
        }
    }
    

    【讨论】:

    • 感谢@Anonymous,如果再次点击,一定要取消勾选吗?请勾选:view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(array.get(getAdapterPosition())){ array.put(getAdapterPosition(), false); }else{ array.put(getAdapterPosition(), true); } notifyDataSetChanged(); } });
    【解决方案2】:

    您可能遗漏了 recylerview 的一些概念。事实是,recyclerview 在每 9 个项目后绑定/回收相同的视图。因此,为了避免这种情况,只需在您的活动中使用setItemViewCacheSize()

    示例:

    contactListAdapter = new ContactsListAdapter(ContactActivity.this, contactArrayList);
            mRecyclerView.setItemViewCacheSize(contactArrayList.size());
            mRecyclerView.setAdapter(contactListAdapter);
    

    public void setItemViewCacheSize(int size) 设置离屏次数 在将视图添加到可能共享的回收对象之前要保留的视图 观景池。屏幕外视图缓存会随时了解 附加适配器,允许 LayoutManager 重用这些视图 未修改,无需返回适配器重新绑定它们。 参数: size - 返回前缓存在屏幕外的视图数 他们到一般回收的视图池

    【讨论】:

    • 也为我工作。
    • 互联网上的最佳解决方案,非常感谢它对我有用
    • 这是一种黑客行为,不建议这样做。因为这只是否定了 recyclerview 的使用,并且由于内存使用过多,整个屏幕可能会变得迟钝
    【解决方案3】:
    public class CardViewDataAdapter extends RecyclerView.Adapter<CardViewDataAdapter.ViewHolder> {
        private List<Student> stList;
        public CardViewDataAdapter(List<Student> students) {
            this.stList = students;
        }
    
    @Override
    public CardViewDataAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      // create a new view
        View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(
        R.layout.cardview_row, null);
    
      // create ViewHolder
    
      ViewHolder viewHolder = new ViewHolder(itemLayoutView);
    
      return viewHolder;
     }
    
     @Override
     public void onBindViewHolder(ViewHolder viewHolder, int position) {
    
      final int pos = position;
    
      viewHolder.tvName.setText(stList.get(position).getName());
    
      viewHolder.tvEmailId.setText(stList.get(position).getEmailId());
    
      viewHolder.chkSelected.setChecked(stList.get(position).isSelected());
    
      viewHolder.chkSelected.setTag(stList.get(position));
    
    
      viewHolder.chkSelected.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
        CheckBox cb = (CheckBox) v;
        Student contact = (Student) cb.getTag();
    
        contact.setSelected(cb.isChecked());
        stList.get(pos).setSelected(cb.isChecked());
    
        Toast.makeText(
          v.getContext(),
          "Clicked on Checkbox: " + cb.getText() + " is "
            + cb.isChecked(), Toast.LENGTH_LONG).show();
       }
      });
    
     }
    
     // Return the size arraylist
     @Override
     public int getItemCount() {
      return stList.size();
     }
    
     public static class ViewHolder extends RecyclerView.ViewHolder {
    
      public TextView tvName;
      public TextView tvEmailId;
    
      public CheckBox chkSelected;
    
      public Student singlestudent;
    
      public ViewHolder(View itemLayoutView) {
       super(itemLayoutView);
    
       tvName = (TextView) itemLayoutView.findViewById(R.id.tvName);
    
       tvEmailId = (TextView) itemLayoutView.findViewById(R.id.tvEmailId);
       chkSelected = (CheckBox) itemLayoutView.findViewById(R.id.chkSelected);
    
      }
    
     }
    
     // method to access in activity after updating selection
     public List<Student> getStudentist() {
      return stList;
     }
    }
    

    更多关于复选框选择的了解,请关注link

    【讨论】:

    • @Shaido & alfakini - 相关答案已经发布,我没有回答相同的解决方案,这就是为什么发布参考链接以加深理解。我认为这将有助于理清概念。
    • @MohammadMisbah 链接将来可能会中断,因此最好在答案本身中包含相关信息。如果信息不能回答问题,可以将其作为评论发布或在现有答案中添加信息。
    • @ Shaido - 是的,你是对的,当然我会更新我的答案。感谢审核。
    【解决方案4】:
    public class SuggestionListAdapter extends RecyclerView.Adapter<SuggestionListAdapter.SuggestionListViewHolder> {
    
    private List<Suggestion> mSuggestionList;
    private Context mContext;
    
    
    
    public class SuggestionListViewHolder extends RecyclerView.ViewHolder{
        private CheckBox mCheckBox;
        private LinearLayout mParent;
    
    
        public SuggestionListViewHolder(View itemView) {
            super(itemView);
            mCheckBox = (CheckBox)itemView.findViewById(R.id.list_display_checkbox);
            mParent =(LinearLayout)itemView.findViewById(R.id.list_parentll);
        }
    }
    
    public SuggestionListAdapter(List<Suggestion> suggestionList, Context context) {
        this.mSuggestionList = suggestionList;
        this.mContext = context;
    }
    
    @Override
    public SuggestionListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View new_suggestion_list_view = LayoutInflater.from(parent.getContext()).inflate(R.layout.suggestion_list,parent,false);
        return new SuggestionListViewHolder(new_suggestion_list_view);
    }
    @Override
    public void onBindViewHolder(final SuggestionListViewHolder holder, final int position) {
    
        final Suggestion suggestion = mSuggestionList.get(position);
    
        holder.mCheckBox.setText(suggestion.getCategory());
        holder.mCheckBox.setOnCheckedChangeListener(null);
        holder.mCheckBox.setSelected(suggestion.isSelected());
        holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked){
                    suggestion.setSelected(true);
                }else {
                    suggestion.setSelected(false);
                }
            }
        });
        holder.mCheckBox.setChecked(suggestion.isSelected());
    }
    
    @Override
    public int getItemCount() {
        return mSuggestionList.size();
    }
    

    }

    看看这个例子,我相信你会发现你做错的地方,你可以解决你的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-29
      相关资源
      最近更新 更多