Voici le XML pour mes articles dans le 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>
Et voici l'adaptateur RecyclerView qui gonfle la mise en page ci-dessus pour chacun de ses éléments:
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));
}
}
Le problème est, disons que j'ai 10 éléments à l'intérieur du RecyclerView. Lorsque j'ai coché la case à cocher sur l'élément 1, 2, 3, puis je fais défiler vers le bas le RecyclerView, tout à coup certains des autres éléments, par exemple les éléments 8, 9 sont cochés. Et quand je fais défiler à nouveau vers le haut, les éléments 1 et 3 sont cochés mais pas l'élément 2. Une idée de pourquoi cela se produit?
android
android-recyclerview
j'en suis
la source
la source
Réponses:
C'est un comportement attendu. Vous ne cochez pas votre case ou non. Vous en sélectionnez un et le titulaire de la vue le garde sélectionné. Vous pouvez ajouter une variable booléenne dans votre objet ObjectIncome et conserver le statut de sélection de votre élément.
Vous pouvez regarder mon exemple. Vous pouvez faire quelque chose comme ça:
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); } }); } }
la source
holder.cbSelect.setOnCheckedChangeListener(null);
avantholder.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); } });
En bref, c'est à cause du recyclage des vues et de leur réutilisation!
comment pouvez-vous éviter cela:
1.Cochez
onBindViewHolder
si vous devez cocher ou décocher les cases. n'oubliez pas de mettre à la fois if et elseif (...) holder.cbSelect.setChecked(true); else holder.cbSelect.setChecked(false);
myItems
tableau! Ainsi, chaque fois qu'une nouvelle vue est affichée, elle lit la dernière statue de l'objet.la source
isChecked
false
pour tous les ensembles de données au démarrage, puisonCheckChanged
je viens de mettre à jour laisChecked
valeur entrue
oufalse
et comme indiqué dans la réponse, implémenter cette vérification cochée ou non.N'UTILISEZ CECI QUE SI VOUS AVEZ UN NOMBRE LIMITÉ D'ARTICLES DANS VOTRE VUE RECYCLEUR.
J'ai essayé d'utiliser la valeur booléenne dans le modèle et de conserver le statut de la case à cocher, mais cela n'a pas aidé dans mon cas. Ce qui a fonctionné pour moi, c'est this.setIsRecyclable (false);
public class ComponentViewHolder extends RecyclerView.ViewHolder { public MyViewHolder(View itemView) { super(itemView); .... this.setIsRecyclable(false); }
Plus d'explications à ce sujet peuvent être trouvées ici https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html#isRecyclable ()
REMARQUE: il s'agit d'une solution de contournement. Pour l'utiliser correctement, vous pouvez vous référer au document qui déclare "Les appels à setIsRecyclable () doivent toujours être appariés (un appel à setIsRecyclabe (false) doit toujours être associé à un appel ultérieur à setIsRecyclable (true)). Les paires d'appels peuvent être imbriquées , car l'état est compté en interne. " Je ne sais pas comment faire cela dans le code, si quelqu'un peut fournir plus de code à ce sujet.
la source
Ajoutez simplement deux méthodes de remplacement de
RecyclerView
@Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { return position; }
la source
Vous pouvez utiliser la classe Model pour suivre la case à cocher de chaque élément recyclerView. La référence complète est de: RecyclerView Checkbox Android
setTag et getTag sont utilisés pour suivre l'état des cases à cocher. Consultez le lien de référence complet pour plus d'informations. Il enseigne également comment envoyer des éléments cochés à NEXTACTIVITY .
Faire un modèle
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; } }
créer integer.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <integer name="btnplusview">1</integer> <integer name="btnpluspos">2</integer> </resources>
Enfin, l'adaptateur ressemble à ceci:
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); } }
}
la source
En utilisant Kotlin, la seule chose qui a résolu ce problème pour moi était d'effacer le
OnCheckedChangeListener
paramètre avant de définir la variable, puis de créer un nouveauOnCheckedChangeListener
aprèschecked
.Je fais ce qui suit dans mon
RecyclerView.ViewHolder
task.setOnCheckedChangeListener(null) task.isChecked = item.status task.setOnCheckedChangeListener { _: CompoundButton, checked: Boolean -> item.status = checked ... do more stuff ... }
la source
Comme indiqué ci-dessus, l'état vérifié de l'objet doit être inclus dans les propriétés de l'objet. Dans certains cas, vous devrez peut-être également modifier l'état de sélection d'objet en cliquant sur l'objet lui-même et laisser la case à cocher informer sur l'état réel (sélectionné ou non). La case à cocher utilisera alors l'état de l'objet à la position réelle de l'adaptateur donné qui est (par défaut / dans la plupart des cas) la position de l'élément dans la liste.
Vérifiez l'extrait ci-dessous, cela peut être utile.
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); } } }
la source
Dans mon cas, cela a fonctionné.
@Override public void onViewRecycled(MyViewHolder holder) { holder.checkbox.setChecked(false); // - this line do the trick super.onViewRecycled(holder); }
la source
Utilisez un tableau pour conserver l'état des éléments
Dans l'adaptateur, utilisez une carte ou un SparseBooleanArray (qui est similaire à une map mais est une paire clé-valeur de int et boolean) pour stocker l'état de tous les éléments de notre liste d'éléments, puis utilisez les clés et les valeurs pour comparer lors du basculement de l'état vérifié
Dans l'adaptateur, créez un
SparseBooleanArray
// sparse boolean array for checking the state of the items private SparseBooleanArray itemStateArray= new SparseBooleanArray();
puis dans le gestionnaire de clic d'élément,
onClick()
utilisez l'état des éléments de l'élément itemStateArray pour vérifier avant de basculer, voici un exemple@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); } }
également, utilisez un tableau booléen clairsemé pour définir l'état vérifié lorsque la vue est liée
@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); } }
et l'adaptateur final sera comme ça
la source
Vous devez séparer les interactions onBindViewHolder (logic) avec CheckBox et les interactions utilisateur avec checkbox. J'ai utilisé OnCheckedChangeListener pour les interactions utilisateur (évidemment) et ViewHolder.bind () pour la logique, c'est pourquoi vous devez définir l'auditeur vérifié sur null avant de configurer le support et une fois que le support est prêt - configurez l'auditeur vérifié pour les interactions utilisateur.
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); } }
la source
Je recommande de ne pas utiliser
checkBox.setOnCheckedChangeListener
dansrecyclerViewAdapter
. Parce que sur le défilement recyclerView,checkBox.setOnCheckedChangeListener
sera déclenché par l'adaptateur. Ce n'est pas sûr . Utilisez plutôtcheckBox.setOnClickListener
pour interagir avec les entrées utilisateur.Par exemple:
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 } } }); }
la source
Le problème de cette solution que j'ai trouvé est, en créant un tableau global statique et en l'utilisant dans "onBindViewHolder" ADAPER CLASS, dans lequel j'ai créé toutes les variables / objets globaux nécessaires.
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); } } }
Ici (IN CONSTRUCTOR of RVADAPTER CLASS), j'ai donné la taille du tableau égale à la taille / non des éléments que je vais afficher dans la vue du recycleur
List<Person> persons; RVAdapter(List<Person> persons){ this.persons = persons; PersonViewHolder.check=new int[persons.size()]; PersonViewHolder.k=persons.size(); }
BindViewHolder, I, Appliqué ce concept sur un bouton, lorsque je clique sur un bouton, l'image de fond du bouton change. L'objet du bouton que j'ai utilisé est des noms comme "upvote", comme "i" tient la position de chaque élément dans la vue du recycleur, je l'ai utilisé comme un index de tableau qui fonctionne comme un drapeau et qui garde la trace de l'état des éléments.
@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); } }
la source
J'ai eu le même problème. Lorsque je cliquais sur le bouton bascule de l'élément dans mon recyclerView, le bouton bascule coché est apparu dans tous les 10 éléments (par exemple, s'il était cliqué dans l'élément avec un index 0, les éléments avec 9, 18, 27 index étaient également cliqués). Tout d'abord, mon code dans onBindViewHolder était:
if (newsItems.get(position).getBookmark() == 1) { holder.getToggleButtonBookmark().setChecked(true); }
Mais ensuite j'ai ajouté la déclaration Else
if (newsItems.get(position).getBookmark() == 1) { holder.getToggleButtonBookmark().setChecked(true); //else statement prevents auto toggling } else{ holder.getToggleButtonBookmark().setChecked(false); }
Et le problème a été résolu
la source
ok il y a beaucoup de réponses ici je posterai mon code et je vais simplement expliquer ce que j'ai fait ... ça peut peut-être aider les juniors comme moi:
1- Objectif:
nous allons créer une liste de ce
RecyclerView
qui aCheckBox
etRadioButton
, quelque chose comme ceci:2- Classe de modèle
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-Mon incroyable adaptateur
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- Dans l'activité, vous leur obtenez quelque chose comme ceci:
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(); } });
la source
J'ai eu le même problème dans une liste RecyclerView avec des commutateurs, et je l'ai résolu en utilisant la réponse @oguzhand, mais avec ce code dans le checkedChangeListener:
if (buttonView.isPressed()) { if (isChecked) { group.setSelected(true); } else { group.setSelected(false); } }else{ if (isChecked) { buttonView.setChecked(false); } else { buttonView.setChecked(true); } }
(Où 'group' est l'entité que je souhaite sélectionner / désélectionner)
la source
classe publique TagYourDiseaseAdapter étend RecyclerView.Adapter {private ReCyclerViewItemClickListener mRecyclerViewItemClickListener; Contexte privé 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); } }
}
la source
cela se produira lors de l'utilisation
setOnCheckedChangeListener
au lieu de cette utilisationsetObClickListener
et à l'intérieur de cela, faites simplement cette manipulation facile:if (list.get(position).isCheck()) { list.get(position).setCheck(false); } else { list.get(position).setCheck(true); }
j'espère que cela aidera quelqu'un si oui + votez pour cette réponse
la source
L'ajout de setItemViewCacheSize (taille int) à recyclerview et la transmission de la taille de la liste ont résolu mon problème.
mycode:
mrecyclerview.setItemViewCacheSize(mOrderList.size()); mBinding.mrecyclerview.setAdapter(mAdapter);
Source: https://stackoverflow.com/a/46951440/10459907
la source
cela est dû à la création répétée de la vue, la meilleure option est de vider le cache avant de définir l'adaptateur
recyclerview.setItemViewCacheSize(your array.size());
la source
Exemple complet de
classe publique ChildAddressAdapter étend 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); } }
}
la source
Ce qui a fonctionné pour moi, c'est d'annuler les écouteurs sur viewHolder lorsque la vue va être recyclée (
onViewRecycled
):override fun onViewRecycled(holder: AttendeeViewHolder) { super.onViewRecycled(holder) holder.itemView.hasArrived.setOnCheckedChangeListener(null); holder.itemView.edit.setOnClickListener { null } }
la source