RecyclerView中的CheckBox继续检查其他项目


93

这是RecyclerView中我商品的XML

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cvItems"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:layout_margin="2dp"
    card_view:cardElevation="0dp"
    card_view:contentPadding="0dp"
    card_view:cardBackgroundColor="#FFFFFF"
    >

    <LinearLayout
        android:orientation="horizontal"
        android:layout_height="fill_parent"
        android:layout_width="fill_parent">
        <TextView
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="0.8"
            android:id="@+id/tvContent"
            android:textSize="15dp"
            android:paddingLeft="5dp"
            android:paddingRight="5dp" />
        <CheckBox
            android:id="@+id/cbSelect"
            android:layout_width="0dip"
            android:layout_weight="0.2"
            android:layout_height="match_parent"
            android:button="@drawable/cb_checked"
            android:gravity="center_horizontal"
            android:textAlignment="center"
            android:layout_gravity="center_horizontal" />
    </LinearLayout>
</android.support.v7.widget.CardView>

这是RecyclerView适配器,可以为其每个项目增加上面的布局:

public class AdapterTrashIncome extends RecyclerView.Adapter<AdapterTrashIncome.ViewHolder> {

    private ArrayList<ObjectIncome> myItems = new ArrayList<>();

    public AdapterTrashIncome(ArrayList<ObjectIncome> getItems, Context context){
        try {
            mContext = context;
            myItems = getItems;
        }catch (Exception e){
            Log.e(FILE_NAME, "51: " + e.toString());
            e.printStackTrace();
        }
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView tvContent;
        public CheckBox cbSelect;

        public ViewHolder(View v) {
            super(v);
            tvContent = (TextView) v.findViewById(R.id.tvContent);
            cbSelect = (CheckBox) v.findViewById(R.id.cbSelect);
        }
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        final ObjectIncome objIncome = myItems.get(position);
        String content = "<b>lalalla</b>";
        holder.tvContent.setText(Html.fromHtml(content));
    }
}

问题是,假设我在RecyclerView中有10个项目。当我选中项目1,2,3上的复选框时,我向下滚动了RecyclerView,突然检查了其他一些项目,例如项目8,9。当我再次向上滚动时,将检查项目1和3,而不是项目2。为什么会这样?


尝试使用此库,请参见ViewStates。滚动时有助于保存状态。
维塔利

Answers:


167

这是预期的行为。您没有选择复选框。您正在选择一个,视图持有者将其保持选中状态。您可以将布尔变量添加到ObjectIncome对象中,并保持项目的选择状态。

您可以看一下我的例子。您可以执行以下操作:

public class AdapterTrashIncome extends RecyclerView.Adapter<AdapterTrashIncome.ViewHolder> {

    private ArrayList<ObjectIncome> myItems = new ArrayList<>();

    public AdapterTrashIncome(ArrayList<ObjectIncome> getItems, Context context){
        try {
            mContext = context;
            myItems = getItems;
            }catch (Exception e){
            Log.e(FILE_NAME, "51: " + e.toString());
            e.printStackTrace();
        }
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView tvContent;
        public CheckBox cbSelect;

        public ViewHolder(View v) {
            super(v);
            tvContent = (TextView) v.findViewById(R.id.tvContent);
            cbSelect = (CheckBox) v.findViewById(R.id.cbSelect);
        }
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        final ObjectIncome objIncome = myItems.get(position);
        String content = "<b>lalalla</b>";
        holder.tvContent.setText(Html.fromHtml(content));

        //in some cases, it will prevent unwanted situations
        holder.cbSelect.setOnCheckedChangeListener(null);

        //if true, your checkbox will be selected, else unselected
        holder.cbSelect.setChecked(objIncome.isSelected());

        holder.cbSelect.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    //set your object's last status
                    objIncome.setSelected(isChecked);
            }
        });

    }
}

19
没用 您必须holder.cbSelect.setOnCheckedChangeListener(null);之前写过holder.cbSelect.setChecked(objIncome.isSelected())
Jemshit Iskenderov

2
是否有任何理由为什么要设置holder.cbSelect.setOnCheckedChangeListener(null); 作品?
2015年

4
@oguzhand嗨,我尝试了您的解决方案,但无论哪种方法都无效:无论是否将侦听器设置为null。
阿巴斯

3
@oguzhand这是中的代码onBindViewHolder@Override public void onBindViewHolder(final ItemHolder holder, int position) { holder.checkBox.setOnCheckedChangeListener(null); holder.checkBox.setSelected(list.get(position).isSelected()); holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { list.get(holder.getAdapterPosition()).setSelected(isChecked); } });
阿巴斯

1
@Suisse您需要在对象中保留复选框状态,因为ViewHolder只是一个持有人。如果有100个项目,则只有大约6-7个(取决于屏幕和布局大小)ViewHolders,并在循环中使用所有这些对象。
的OguzhanDöngül

22

简而言之,这是因为回收视图并再次使用它们!

如何避免这种情况:

1.在onBindViewHolder检查中是否应该选中或取消选中复选框。别忘了把if和else都放

if (...)
    holder.cbSelect.setChecked(true);
else
    holder.cbSelect.setChecked(false);
  1. 放置一个侦听器复选框!每当其检查的雕像更改时,也要在myItems数组中更新相应的对象!因此,每当显示新视图时,它都会读取对象的最新雕像。

您的第二点是关键。尽管它在某种情况下效果最好,但当初始数据集也包含有关已检查状态的信息时(对我来说就是这种情况)
Attila Orosz

1
这是更直接,更正确的答案。setCheck在onBindViewHolder中对真与假都是关键
Beeing Jk

在我的情况下,我必须isChecked false使用启动时所有数据集的默认值将数据保存在数据模型中,然后onCheckChanged我将isChecked值更新为trueor,false并且如答案工具中所述检查或不选中。
阿里·塔莫尔

21

仅在回收站视图中项目数量有限时才使用此功能。
我尝试在模型中使用布尔值并保持复选框状态,但对我而言没有帮助。对我有用的this.setIsRecyclable(false);

public class ComponentViewHolder extends RecyclerView.ViewHolder {
    public MyViewHolder(View itemView) {
        super(itemView);
        ....
        this.setIsRecyclable(false);
    }

有关此问题的更多说明,请参见https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#isRecyclable()

注意:这是一种解决方法。要正确使用它,您可以参考说明以下内容的文档:“对setIsRecyclable()的调用应始终配对(对setIsRecyclabe(false)的调用应始终与以后对setIsRecyclable(true)的调用匹配。)可以成对嵌套,因为该状态是内部引用计数的。” 如果有人可以提供更多代码,我不知道如何用代码来实现。


请您能解释一下如何使用它吗?
UserName_Untold

43
是不是浪费了recyclerView背后的逻辑?
Eren

3
我尝试使用长列表解决了随机检查问题,但是当我向下滚动并重新滚动长列表时,选中的复选框消失了:(
SonDang

2
使视图不可回收不是一个好主意,因为它会耗尽内存,并且您将失去回收视图的大部分优势。
亚瑟

我同意@ eren130和Arthur。我已经编辑了这篇文章,非常感谢您能提出一种使用setIsRecyclable(true / false);的方法。正确地。
Rana Ranvijay Singh'7

13

只需添加两个的覆盖方法 RecyclerView

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemViewType(int position) {
    return position;
}

2
不要那样做!它将绕过recyclerView回收机制,并失去使用它的全部要点。
Hanoch Moreno

1
不,它不会,它只是返回视图回收器中每个回收视图的确切位置。
哈里斯·雷迪

1
Harish,也许我缺少了一些东西,但是据我所知,通过这样做,您实际上告诉适配器项目类型的数量就是项目计数。意思是因为没有相似的视图,所以无法回收任何物品。虽然很容易测试。只需在onBindViewHolder内记录viewHolder.itemView引用,然后查看是否有两个viewHolders持有相同的视图引用。该测试应列在长清单上,以便执行回收系统。
Hanoch Moreno

3
它完美地苏醒,挽救了我的一天。
昆丹

5
如果您的recyclerview中有超过100个项目,此解决方案将立即加载所有项目,如果您有图像,这可能会导致OutOfMemoryException,否则,此解决方案非常完美@Kundan
Harish Reddy

11

您可以使用Model类来跟踪每个recyclerView项目的复选框。完整参考资料来自:Android RecyclerView Checkbox

setTaggetTag用于跟踪复选框状态。查看完整的参考链接以获取更多信息。它还教导如何将选中的项目发送到NEXTACTIVITY

制作模型

public class Model {

    private boolean isSelected;
    private String animal;

    public String getAnimal() {
        return animal;
    }

    public void setAnimal(String animal) {
        this.animal = animal;
    }

    public boolean getSelected() {
        return isSelected;
    }

    public void setSelected(boolean selected) {
        isSelected = selected;
    }
}

创建integer.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="btnplusview">1</integer>
    <integer name="btnpluspos">2</integer>
</resources>

最后,适配器看起来像这样:

 import android.content.Context;
 import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
    import android.view.View;
 import android.view.ViewGroup;
 import android.widget.CheckBox;
 import android.widget.TextView;
 import android.widget.Toast;

 import java.util.ArrayList;


  public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {

private LayoutInflater inflater;
public static ArrayList<Model> imageModelArrayList;
private Context ctx;

public CustomAdapter(Context ctx, ArrayList<Model> imageModelArrayList) {

    inflater = LayoutInflater.from(ctx);
    this.imageModelArrayList = imageModelArrayList;
    this.ctx = ctx;
}

@Override
public CustomAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = inflater.inflate(R.layout.rv_item, parent, false);
    MyViewHolder holder = new MyViewHolder(view);

    return holder;
}

@Override
public void onBindViewHolder(final CustomAdapter.MyViewHolder holder, int position) {

    holder.checkBox.setText("Checkbox " + position);
    holder.checkBox.setChecked(imageModelArrayList.get(position).getSelected());
    holder.tvAnimal.setText(imageModelArrayList.get(position).getAnimal());

   // holder.checkBox.setTag(R.integer.btnplusview, convertView);
    holder.checkBox.setTag(position);
    holder.checkBox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Integer pos = (Integer) holder.checkBox.getTag();
            Toast.makeText(ctx, imageModelArrayList.get(pos).getAnimal() + " clicked!", Toast.LENGTH_SHORT).show();

            if (imageModelArrayList.get(pos).getSelected()) {
                imageModelArrayList.get(pos).setSelected(false);
            } else {
                imageModelArrayList.get(pos).setSelected(true);
            }
        }
    });


}

@Override
public int getItemCount() {
    return imageModelArrayList.size();
}

class MyViewHolder extends RecyclerView.ViewHolder {

    protected CheckBox checkBox;
    private TextView tvAnimal;

    public MyViewHolder(View itemView) {
        super(itemView);

        checkBox = (CheckBox) itemView.findViewById(R.id.cb);
        tvAnimal = (TextView) itemView.findViewById(R.id.animal);
    }

}

}


3

使用Kotlin,对我来说唯一解决此问题的方法是清除OnCheckedChangeListener设置变量之前,然后创建一个新的OnCheckedChangeListenerafter checked

我在我做以下 RecyclerView.ViewHolder

task.setOnCheckedChangeListener(null)
task.isChecked = item.status
task.setOnCheckedChangeListener { _: CompoundButton, checked: Boolean ->
    item.status = checked
    ...
    do more stuff
    ...
}

这是完美的工作。我不为什么,但这仅在使用KOTLIN的任何人中有效!
Aditya S.

2

如上所述,对象的检查状态应包含在对象属性中。在某些情况下,您可能还需要通过单击对象本身来更改对象选择状态,并让CheckBox告知其实际状态(选中或未选中)。然后,该复选框将在给定适配器的实际位置(默认情况下/在大多数情况下)中元素在列表中的位置使用对象的状态。

检查下面的代码段,它可能会很有用。

import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class TakePicImageAdapter extends RecyclerView.Adapter<TakePicImageAdapter.ViewHolder>{
    private Context context;
    private List<Image> imageList;

    public TakePicImageAdapter(Context context, List<Image> imageList) {
        this.context = context;
        this.imageList = imageList;
    }

    @Override
    public TakePicImageAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(context).inflate(R.layout.image_item,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final TakePicImageAdapter.ViewHolder holder, final int position) {
        File file=new File(imageList.get(position).getPath());
        try {
            Bitmap bitmap= MediaStore.Images.Media.getBitmap(context.getContentResolver(), Uri.fromFile(file));
            holder.image.setImageBitmap(bitmap
            );
        } catch (IOException e) {
            e.printStackTrace();
        }
        holder.selectImage.setOnCheckedChangeListener(null);
        holder.selectImage.setChecked(imageList.get(position).isSelected());
        holder.selectImage.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                holder.selectImage.setChecked(isChecked);
                imageList.get(position).setSelected(isChecked);
            }
        });
        holder.image.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (imageList.get(position).isSelected())
                {
                    imageList.get(position).setSelected(false);
                    holder.selectImage.setChecked(false);
                }else
                {
                    imageList.get(position).setSelected(true);
                    holder.selectImage.setChecked(true);
                }
            }
        });

    }

    @Override
    public int getItemCount() {
        return imageList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ImageView image;public CheckBox selectImage;
        public ViewHolder(View itemView) {
            super(itemView);
            image=(ImageView)itemView.findViewById(R.id.image);
            selectImage=(CheckBox) itemView.findViewById(R.id.ch);

        }
    }
}


2

就我而言,这行得通。

@Override
public void onViewRecycled(MyViewHolder holder) {
    holder.checkbox.setChecked(false); // - this line do the trick
    super.onViewRecycled(holder);
}

2

使用数组保存项目的状态

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

最终的适配器将像这样


1

您需要将与CheckBox的onBindViewHolder(logic)交互与与Checkbox的用户交互分开。我使用OnCheckedChangeListener进行用户交互(显然),使用ViewHolder.bind()进行逻辑,这就是为什么在设置所有者之前和所有者准备好之后,需要将选中的侦听器设置为null-为用户交互配置选中的侦听器。

boolean[] checkedStatus = new boolean[numberOfRows];

@Override
        public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
        final ViewHolderItem itemHolder = (ViewHolderItem) holder;

        //holder.bind should not trigger onCheckedChanged, it should just update UI
        itemHolder.checkBox.setOnCheckedChangeListener(null);

        itemHolder.bind(position);

        itemHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    checkedStatus[holder.getAdapterPosition()] = true;
                    performCheckedActions(); //your logic here
                } else {
                    checkedStatus[holder.getAdapterPosition()] = false;
                    performUncheckedActions(); //your logic here
                }
            }
        });
    }

public void bind(int position) {
            boolean checked = checkedStatus[position];
            if (checked) {
                checkBox.setChecked(false);
            } else {
                checkBox.setChecked(true);
            }
        }

1

我建议不要使用checkBox.setOnCheckedChangeListenerrecyclerViewAdapter。因为在滚动recyclerView时,checkBox.setOnCheckedChangeListener将被适配器触发。这不安全。相反,使用checkBox.setOnClickListener与用户输入进行交互。

例如:

     public void onBindViewHolder(final ViewHolder holder, int position) {
        /*
         .
         .
         .
         .
         .
         .
        */

        holder.checkBoxAdapterTasks.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean isChecked =  holder.checkBoxAdapterTasks.isChecked();
                if(isChecked){
                    //checkBox clicked and checked
                }else{
                    //checkBox clicked and unchecked
                }

            }
        });

    }

1

我发现此解决方案的问题是,通过创建静态全局数组并将其用于“ onBindViewHolder” ADAPER CLASS中,在该数组中,我创建了所需的所有全局变量/对象。

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder> {
private Context context;
public static class PersonViewHolder extends RecyclerView.ViewHolder {

    CardView cv;
    TextView question,category;
    TextView personAge;
    ImageView upvote;
    Button b1;
    public static int k;
    private int visibleThreshold = 5;
    public static int i=0;
     static int  check[]; //Static array
    PersonViewHolder(View itemView,int i) {
        super(itemView);
        if(i==PersonViewHolder.k)
        {
            b1=(Button)itemView.findViewById(R.id.loadmore);

        }
        else
        {
            cv = (CardView)itemView.findViewById(R.id.cv);
            question = (TextView)itemView.findViewById(R.id.question);
            category = (TextView)itemView.findViewById(R.id.text_categ);
            personAge = (TextView)itemView.findViewById(R.id.text1);
            upvote = (ImageView)itemView.findViewById(R.id.upvote);

        }

    }

}

在这里(在RVADAPTER CLASS的构造函数中),我给数组指定的大小等于/否要在回收器视图中显示的项目的大小

List<Person> persons;

RVAdapter(List<Person> persons){
    this.persons = persons;
    PersonViewHolder.check=new int[persons.size()];
    PersonViewHolder.k=persons.size();
}

BindViewHolder,我在按钮上应用了此概念,当我单击按钮时,按钮的背景图像发生了变化。我使用的按钮对象的名称为“ upvote”,因为“ i”在回收器视图中保持每个项目的位置,我将其用作数组的索引,该数组充当标志并跟踪元素的状态。

@Override
public void onBindViewHolder(final PersonViewHolder personViewHolder, final int i) {
    if(i==PersonViewHolder.k) {
        personViewHolder.b1.setText("load more");

    }
    else
     {
        personViewHolder.question.setText(persons.get(i).name);
        personViewHolder.personAge.setText(persons.get(i).age);

         if(personViewHolder.check[i]==0)
         {personViewHolder.upvote.setBackgroundResource(R.drawable.noupvote);
         }
         else
         {
             personViewHolder.upvote.setBackgroundResource(R.drawable.upvote);

         }

         personViewHolder.upvote.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 if(personViewHolder.check[i]==0)
                 {personViewHolder.check[i]=1;
                     personViewHolder.upvote.setBackgroundResource(R.drawable.upvote);


                 }
                 else
                 {personViewHolder.check[i]=0;
                     personViewHolder.upvote.setBackgroundResource(R.drawable.noupvote);

                 }


             }
         });
        // personViewHolder.personPhoto.setImageResource(persons.get(i).photoId);
    }

}

1

我有同样的问题。当我在recyclerView中单击项目的切换按钮时,选中的切换按钮会出现在第10个项目中(例如,如果在索引为0的项目中单击了切换按钮,那么也要单击具有9、18、27索引的项目)。首先,我在onBindViewHolder中的代码是:

if (newsItems.get(position).getBookmark() == 1) {
            holder.getToggleButtonBookmark().setChecked(true);
        }

但后来我添加了其他声明

if (newsItems.get(position).getBookmark() == 1) {
            holder.getToggleButtonBookmark().setChecked(true);
//else statement prevents auto toggling
        } else{
            holder.getToggleButtonBookmark().setChecked(false);
        }

问题解决了


谢谢。如果其他部分在回收同一视图时默认选中,则该复选框将清除该复选框。
Adarsh Vijayan P

1

还好有很多答案在这里我将发布我的代码,而我只是简单地解释一下我所做的...这可能会帮助像我这样的初中生:D。

1-目标:

我们将创建RecyclerView具有CheckBox和的列表RadioButton,如下所示:

在此处输入图片说明 2-模型类

public class ModelClass {
private String time;
private boolean checked;
private boolean free;
private boolean paid;

public TherapistScheduleModel(String time, boolean checked, boolean free, boolean paid) {
    this.time = time;
    this.checked = checked;
    this.free = free;
    this.paid = paid;
}

public boolean isFree() {
    return free;
}

public void setFree(boolean free) {
    this.free = free;
}

public boolean isPaid() {
    return paid;
}

public void setPaid(boolean paid) {
    this.paid = paid;
}

public String getTime() {
    return time;
}

public void setTime(String time) {
    this.time = time;
}

public boolean getChecked() {
    return checked;
}

public void setChecked(boolean checked) {
    this.checked= checked;
}
}

3-我的惊人适配器

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private ListAllListeners listAllListeners;
private ArrayList<ModelClass> mDataList;

public MyAdapter(Context context, ArrayList<ModelClass> mDataList,
                             ListAllListeners listAllListeners) {
    this.mDataList = mDataList;
    this.listAllListeners = listAllListeners;
    this.context = context;
}

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View view = inflater.inflate(R.layout.single_view, parent, false);
    return new MyViewHolder(view);
}

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

@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
     //important to:
    //setOnCheckedChangeListener to 'null'
    holder.checkBoxTime.setOnCheckedChangeListener(null);
    holder.freeRB.setOnCheckedChangeListener(null);
    holder.paidRB.setOnCheckedChangeListener(null);

    //Check Box
            holder.checkBoxTime.setText(mDataList.get(holder.getAdapterPosition()).getTime());
    //here we check if the item is checked or not from the model.
    if(mDataList.get(holder.getAdapterPosition()).getChecked())
        holder.checkBoxTime.setChecked(true);
    else
        holder.checkBoxTime.setChecked(false);

    holder.checkBoxTime.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            if (b) {
                mDataList.get(holder.getAdapterPosition()).setChecked(true);
                listAllListeners.onItemCheck(holder.checkBoxTime.getText().toString(), holder.getAdapterPosition());
            }
            else {
                mDataList.get(holder.getAdapterPosition()).setChecked(false);
                listAllListeners.onItemUncheck(holder.checkBoxTime.getText().toString(), holder.getAdapterPosition());
            }
        }
    });

    //Radio Buttons

    if(mDataList.get(holder.getAdapterPosition()).isFree())
        holder.freeRB.setChecked(true);
    else
        holder.freeRB.setChecked(false);
    holder.freeRB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            if (b) {
                mDataList.get(holder.getAdapterPosition()).setFree(true);
                listAllListeners.onFreeCheck(holder.freeRB.getText().toString(), holder.getAdapterPosition());
            } else {
                mDataList.get(holder.getAdapterPosition()).setFree(false);
                listAllListeners.onFreeUncheck(holder.freeRB.getText().toString(), holder.getAdapterPosition());
            }
        }
    });

   //***and so on to paidRB***

}//end onBindViewHolder()

public interface ListAllListeners {
//here is a list of clicked listeners to use them as you want ;).
//you can get a list of checked or unChecked of all 
        void onItemCheck(String checkBoxName, int position);
        void onItemUncheck(String checkBoxName, int position);
        void onFreeCheck(String name, int pos);
        void onFreeUncheck(String name, int pos);
        void onPaidCheck(String name, int pos);
        void onPaidUncheck(String name, int pos);
    }

    class MyViewHolder extends RecyclerView.ViewHolder {

        CheckBox checkBoxTime;
        RadioButton freeRB, paidRB;

        MyViewHolder(View itemView) {
            super(itemView);
            checkBoxTime = itemView.findViewById(R.id.timeCheckBox);
            freeRB = itemView.findViewById(R.id.freeRadioBtn);
            paidRB = itemView.findViewById(R.id.paidRadioBtn);
        }
    }//end class MyViewHolder

    }//end class

3-在活动中,您会得到如下信息:

myAdapter= new MyAdapter(getActivity().getApplicationContext(), mDataList,
                new MyAdapter.ListAllListeners() {

                    @Override
                    public void onItemCheck(String checkBoxName, int position) {
                        Toast.makeText(getActivity(), "" + checkBoxName + "  " + position, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onItemUncheck(String checkBoxName, int position) {
                        Toast.makeText(getActivity(), "" + checkBoxName + "  " + position, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onFreeCheck(String name, int position) {

                        Toast.makeText(getActivity(), "" + name + "  " + position, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onFreeUncheck(String name, int position) {

                        Toast.makeText(getActivity(), "" + name + "  " + position, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onPaidCheck(String name, int position) {

                        Toast.makeText(getActivity(), "" + name + "  " + position, Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onPaidUncheck(String name, int position) {

                        Toast.makeText(getActivity(), "" + name + "  " + position, Toast.LENGTH_SHORT).show();
                    }
                });

0

我在带有开关的RecyclerView列表中遇到了相同的问题,并使用@oguzhand答案解决了该问题,但在checkedChangeListener中包含以下代码:

if (buttonView.isPressed()) {
    if (isChecked) {
        group.setSelected(true);
    } else {
        group.setSelected(false);
    }
}else{
    if (isChecked) {
        buttonView.setChecked(false);
    } else {
        buttonView.setChecked(true);
    }
}

(其中“组”是我要选择/取消选择的实体)


0

公共类TagYourDiseaseAdapter扩展了RecyclerView.Adapter {私有ReCyclerViewItemClickListener mRecyclerViewItemClickListener; 私有上下文mContext;

List<Datum> deviceList = Collections.emptyList();

/**
 * Initialize the values
 *
 * @param context : context reference
 * @param devices : data
 */

public TagYourDiseaseAdapter(Context context, List<Datum> devices,
                             ReCyclerViewItemClickListener mreCyclerViewItemClickListener) {
    this.mContext = context;
    this.deviceList = devices;
    this.mRecyclerViewItemClickListener = mreCyclerViewItemClickListener;
}


/**
 * @param parent   : parent ViewPgroup
 * @param viewType : viewType
 * @return ViewHolder
 * <p>
 * Inflate the Views
 * Create the each views and Hold for Reuse
 */
@Override
public TagYourDiseaseAdapter.OrderHistoryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_tag_disease, parent, false);
    TagYourDiseaseAdapter.OrderHistoryViewHolder myViewHolder = new TagYourDiseaseAdapter.OrderHistoryViewHolder(view);
    return myViewHolder;
}


/**
 * @param holder   :view Holder
 * @param position : position of each Row
 *                 set the values to the views
 */
@Override
public void onBindViewHolder(final TagYourDiseaseAdapter.OrderHistoryViewHolder holder, final int position) {
    Picasso.with(mContext).load(deviceList.get(position).getIconUrl()).into(holder.document);
    holder.name.setText(deviceList.get(position).getDiseaseName());

    holder.radioButton.setOnCheckedChangeListener(null);
    holder.radioButton.setChecked(deviceList.get(position).isChecked());

    //if true, your checkbox will be selected, else unselected
    //holder.radioButton.setChecked(objIncome.isSelected());

    holder.radioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            deviceList.get(position).setChecked(isChecked);
        }
    });


}

@Override
public int getItemCount() {
    return deviceList.size();
}


/**
 * Create The view First Time and hold for reuse
 * View Holder for Create and Hold the view for ReUse the views instead of create again
 * Initialize the views
 */

public class OrderHistoryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    ImageView document;
    TextView name;
    CheckBox radioButton;

    public OrderHistoryViewHolder(View itemView) {
        super(itemView);
        document = itemView.findViewById(R.id.img_tag);
        name = itemView.findViewById(R.id.text_tag_name);
        radioButton = itemView.findViewById(R.id.rdBtn_tag_disease);
        radioButton.setOnClickListener(this);
        //this.setIsRecyclable(false);
    }


    @Override
    public void onClick(View view) {
        mRecyclerViewItemClickListener.onItemClickListener(this.getAdapterPosition(), view);
    }
}

}


0

这将在使用setOnCheckedChangeListener而不是使用时发生,setObClickListener并且只需执行以下简单操作即可:

   if (list.get(position).isCheck())
            {
                list.get(position).setCheck(false);
            }
            else
            {
                list.get(position).setCheck(true);
            }

注意:在您的列表模型中,添加一个带有名称的布尔变量,check并为其设置getter和setter,在上述情况下,我的是setCheck和isCheck

希望它能对某人有帮助+投票给这个答案



0

这是由于一次又一次地创建视图,最好的选择是在设置适配器之前清除缓存

recyclerview.setItemViewCacheSize(your array.size());

0

完整的示例
公共类ChildAddressAdapter扩展了RecyclerView.Adapter <ChildAddressAdapter.CartViewHolder> {

private Activity context;
private List<AddressDetail> addressDetailList;
private int selectedPosition = -1;

public ChildAddressAdapter(Activity context, List<AddressDetail> addressDetailList) {
    this.context = context;
    this.addressDetailList = addressDetailList;
}

@NonNull
@Override
public CartViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    LayoutInflater inflater = LayoutInflater.from(context);
    View myView = inflater.inflate(R.layout.address_layout, parent, false);
    return new CartViewHolder(myView);
}

@Override
public void onBindViewHolder(@NonNull CartViewHolder holder, int position) {

    holder.adress_checkbox.setOnClickListener(view -> {
        selectedPosition = holder.getAdapterPosition();
        notifyDataSetChanged();
    });

    if (selectedPosition==position){
        holder.adress_checkbox.setChecked(true);
    }
    else {
        holder.adress_checkbox.setChecked(false);
    }


}

@Override
public int getItemCount() {
    return  addressDetailList.size();
}

class CartViewHolder extends RecyclerView.ViewHolder
{
    TextView address_text,address_tag;
    CheckBox adress_checkbox;

    CartViewHolder(View itemView) {
        super(itemView);
        address_text = itemView.findViewById(R.id.address_text);
        address_tag = itemView.findViewById(R.id.address_tag);
        adress_checkbox = itemView.findViewById(R.id.adress_checkbox);
    }
}

}


-1

对我有用的是在要回收视图时使viewHolder上的侦听器无效(onViewRecycled):

 override fun onViewRecycled(holder: AttendeeViewHolder) {
            super.onViewRecycled(holder)
            holder.itemView.hasArrived.setOnCheckedChangeListener(null);
            holder.itemView.edit.setOnClickListener { null }
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.