Java 在recyclerView中滚动时如何保持复选框状态?

Java 在recyclerView中滚动时如何保持复选框状态?,java,android,checkbox,android-recyclerview,Java,Android,Checkbox,Android Recyclerview,我已经看过了,但是我还没有能够调整这些解决方案来解决我的问题。你能帮忙吗 我选中复选框,在myrecyclerview中向下滚动,当我向上滚动时,复选框被取消选中,或者其他不同的复选框被选中 我明白发生的原因-如上所述:您应该在onBindViewHolder中添加一个boolean变量,以保持项目的选择状态,我相信我正在这样做: theContactsList.get(pos).setSelected(isChecked); 但复选框状态仍然没有保留 这是我的密码: @Override

我已经看过了,但是我还没有能够调整这些解决方案来解决我的问题。你能帮忙吗

我选中复选框,在my
recyclerview
中向下滚动,当我向上滚动时,复选框被取消选中,或者其他不同的复选框被选中

我明白发生的原因-如上所述:您应该在
onBindViewHolder
中添加一个
boolean变量,以保持项目的选择状态,我相信我正在这样做:

theContactsList.get(pos).setSelected(isChecked);
但复选框状态仍然没有保留

这是我的密码:

  @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
        //bind the views into the ViewHolder
        //selectPhoneContact is an instance of the SelectPhoneContact class.
        //We will assign each row of the recyclerview to contain details of selectPhoneContact:

        //The number of rows will match the number of phone contacts
        final SelectPhoneContact selectPhoneContact = theContactsList.get(position);

        //if the row is a matching contact
        if (viewHolder.getItemViewType() == 1)

        {
            //in the title textbox in the row, put the corresponding name etc...
            ((MatchingContact) viewHolder).title.setText(selectPhoneContact.getName());
            ((MatchingContact) viewHolder).phone.setText(selectPhoneContact.getPhone());
            //((MatchingContact) viewHolder).check.setText("Cheeckbox" + position);
            ((MatchingContact) viewHolder).check.setChecked(theContactsList.get(position).isSelected);
            ((MatchingContact) viewHolder).check.setTag(position);

          //  ((MatchingContact) viewHolder).check.setChecked(selectPhoneContact.isSelected());



            ((MatchingContact) viewHolder).check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
           // ((MatchingContact) viewHolder).check.setOnClickListener(new CompoundButton.OnClickListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
                    //pos is the row number that the clicked checkbox exists in
                    Integer pos = (Integer) ((MatchingContact) viewHolder).check.getTag();

                    //set the value of the checkbox accordingly onCheckedChange,
                    //to true or false
                    theContactsList.get(pos).setSelected(isChecked);

                    if(isChecked == true ) {
                       // ((MatchingContact) viewHolder).check.setChecked(true);
                        Toast.makeText(context_type, theContactsList.get(pos).getPhone() + " clicked!", Toast.LENGTH_SHORT).show();

                    }

                    else {
                       // ((MatchingContact) viewHolder).check.setChecked(false);
                        Toast.makeText(context_type, theContactsList.get(pos).getPhone() + " unclicked!", Toast.LENGTH_SHORT).show();

                    }

                }
            });

            }

    }

在回收器适配器中有一个
HashMap
实例。键应该是唯一定义每个项的东西,值指示是否选中该项。无论何时单击复选框,都要调用
map.put(item.getId(),!map.get(item.getId())
(不要忘记检查初始不存在的大小写)。最后在
onBindViewHolder()中调用
方法,始终根据
HashMap

中的状态保持设置项目的复选框,罪魁祸首是您的
OnCheckedChangeListener
-请记住,即使以编程方式更改检查状态,它也会触发

这就是您的实现目前正在发生的情况:

  • 将ViewHolder 1绑定到位置0
  • 向下滚动时,将卸下视图保持架1
  • 重新使用视图保持架1并将其绑定到位置5(示例)
  • 然后执行以下操作:

    ((MatchingContact) viewHolder).check.setChecked(theContactsList.get(5).isSelected);
    ((MatchingContact) viewHolder).check.setTag(5);
    
    但是复选框已经有一个
    OnCheckedChangeListener
    ,所以只要调用
    setChecked()
    ,它就会被执行,这种情况会发生:

    // 0 is the tag you assigned to a view, but we're binding item 5 now
    theContactsList.get(0).setSelected(isChecked);
    
    您有效地将检查状态0设置为状态5(很可能为false)

    在滚动列表时,您还创建了大量的
    OnCheckedChangeListener
    对象。在ViewHolders构造函数中,您只能创建一个对象,因为调用它时会获取当前位置,所以它也可以正常工作


    对于解决方案,只需将
    setTag()
    移到更高的位置(在
    setChecked()
    之前),但老实说,您应该在
    OnCheckedChangeListener
    中使用
    getAdapterPosition()
    ,而不是在代码顶部使用标记。

    尝试使用
    viewHolder.setIsRecyclable(false);

     @Override
        public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
        viewHolder.setIsRecyclable(false);
    
        //other stuff
    }
    

    在我看来,最好是将选中状态保存到模型类或列表中。@Max您会推荐任何帖子/教程吗?您的实现似乎是正确的。您正在将复选框状态保存在列表中。您可以尝试一件事吗?在检查itemViewType,
    (MatchingContact)后,将这一行放在
    onBindView
    的顶部setOnCheckedChangeListener(null)
    @Napster尝试过,但没有修复。我正在执行下面乌古尔坎的建议,将随时通知您。我将保留您上面所说的代码行,因为我确实相信从我所读到的内容来看,它是有益的,而不是有害的。@max是对的!您应该在模型中保存检查状态。也可以使用此库,请参见ViewState