Вот XML для моих элементов в RecyclerView
<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));
}
}
Проблема в том, что, допустим, у меня есть 10 элементов внутри RecyclerView. Когда я установил флажок на элементе 1,2,3, я прокручиваю RecyclerView вниз, внезапно проверяются некоторые другие элементы, например элементы 8,9. И когда я снова прокручиваю вверх, отмечены пункты 1 и 3, но не пункт 2. Есть идеи, почему это происходит?
Ответы:
Это ожидаемое поведение. Вы не устанавливаете флажок установлен или нет. Вы выбираете один, и держатель просмотра сохраняет его выбранным. Вы можете добавить логическую переменную в свой объект 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); } }); } }
источник
holder.cbSelect.setOnCheckedChangeListener(null);
раньшеholder.cbSelect.setChecked(objIncome.isSelected())
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. Установите
onBindViewHolder
флажок, следует ли вам устанавливать или снимать флажки. не забудьте поставить if и elseif (...) holder.cbSelect.setChecked(true); else holder.cbSelect.setChecked(false);
myItems
массиве! поэтому всякий раз, когда отображается новый вид, он считывает самую новую статую объекта.источник
isChecked
false
по умолчанию для всех данных, установленных при запуске, затемonCheckChanged
я просто обновилisChecked
значение доtrue
илиfalse
и, как сказано в ответе, реализует проверку либо проверено, либо нет.ИСПОЛЬЗУЙТЕ ЭТО ТОЛЬКО ЕСЛИ У ВАС ОГРАНИЧЕННОЕ КОЛИЧЕСТВО ДЕТАЛЕЙ В ПРОСМОТРЕ РЕЦИКЛЕР
Я попытался использовать логическое значение в модели и сохранить статус флажка, но в моем случае это не помогло. У меня сработало 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)). Пары вызовов могут быть вложенными , поскольку состояние является внутренним подсчетом ссылок ". Я не знаю, как это сделать в коде, если кто-то может предоставить больше кода по этому поводу.
источник
Просто добавьте два метода переопределения
RecyclerView
@Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { return position; }
источник
Вы можете использовать класс Model для отслеживания каждого флажка элемента recyclerView. Полная ссылка взята из: RecyclerView Checkbox Android
setTag и getTag используются для отслеживания статуса флажка. Проверьте полную ссылку для получения дополнительной информации. Он также учит, как отправлять отмеченные элементы в 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); } }
}
источник
Используя Kotlin, единственное, что решило эту проблему для меня, - это очистить
OnCheckedChangeListener
перед установкой переменной, а затем создать новуюOnCheckedChangeListener
послеchecked
установки.Я делаю следующее в моем
RecyclerView.ViewHolder
task.setOnCheckedChangeListener(null) task.isChecked = item.status task.setOnCheckedChangeListener { _: CompoundButton, checked: Boolean -> item.status = checked ... do more stuff ... }
источник
Как указано выше, отмеченное состояние объекта должно быть включено в свойства объекта. В некоторых случаях может потребоваться также изменить состояние выбора объекта, щелкнув сам объект, и позволить 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); } } }
источник
В моем случае это сработало.
@Override public void onViewRecycled(MyViewHolder holder) { holder.checkbox.setChecked(false); // - this line do the trick super.onViewRecycled(holder); }
источник
Используйте массив для хранения состояния элементов
В адаптере используйте Map или SparseBooleanArray (который похож на карту, но представляет собой пару ключ-значение 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); } }
и финальный адаптер будет таким
источник
Вам необходимо разделить взаимодействия onBindViewHolder (логики) с 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); } }
источник
Я рекомендую не использовать
checkBox.setOnCheckedChangeListener
вrecyclerViewAdapter
. Потому что при прокрутке recyclerViewcheckBox.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 } } }); }
источник
Проблема этого решения, которое я нашел, заключается в создании статического глобального массива и использовании его в «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); } } }
Здесь (IN CONSTRUCTOR of RVADAPTER CLASS) я дал размер массива, равный размеру / количеству элементов, которые я собираюсь отображать в представлении ресайклера
List<Person> persons; RVAdapter(List<Person> persons){ this.persons = persons; PersonViewHolder.check=new int[persons.size()]; PersonViewHolder.k=persons.size(); }
BindViewHolder, I, применил эту концепцию к кнопке, когда я нажимаю на кнопку, фоновое изображение кнопки изменяется. объект кнопки, которую я использовал, называется «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); } }
источник
У меня была такая же проблема. Когда я нажимал кнопку переключения элемента в моем 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); }
И проблема была решена
источник
хорошо есть много ответов здесь я отправлю свой код и я просто объяснить , что я сделал ... это , возможно , помочь юниорам , как я: 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- В Activity вы получаете что-то вроде этого:
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(); } });
источник
У меня была такая же проблема в списке 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); } }
(Где «группа» - это объект, который я хочу выбрать / отменить выбор)
источник
открытый класс 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); } }
}
источник
это произойдет при использовании
setOnCheckedChangeListener
вместо этого использованияsetObClickListener
и внутри этого простого дескриптора:if (list.get(position).isCheck()) { list.get(position).setCheck(false); } else { list.get(position).setCheck(true); }
надеюсь, что это поможет кому-то, если да + проголосуйте за этот ответ
источник
Добавление setItemViewCacheSize (int size) в recyclerview и передача размера списка решили мою проблему.
мой код:
mrecyclerview.setItemViewCacheSize(mOrderList.size()); mBinding.mrecyclerview.setAdapter(mAdapter);
Источник: https://stackoverflow.com/a/46951440/10459907
источник
это связано с тем, что снова и снова создается представление, лучший вариант - очистить кеш перед настройкой адаптера
recyclerview.setItemViewCacheSize(your array.size());
источник
Полный пример
открытого класса 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); } }
}
источник
Что сработало для меня, так это обнулить слушателей на viewHolder, когда представление будет переработано (
onViewRecycled
):override fun onViewRecycled(holder: AttendeeViewHolder) { super.onViewRecycled(holder) holder.itemView.hasArrived.setOnCheckedChangeListener(null); holder.itemView.edit.setOnClickListener { null } }
источник