Причина, по которой вы не можете сделать это, состоит в том, что список доступен для записи. Предположим, что это было законным, и посмотрите, что пойдет не так:
List & lt; Cat & gt; cats = new List & lt; Cat & gt; (); Список & л; Животное & GT; животные = кошки; // Проблемы пивоварения ... animals.Add (новая собака ()); // эй, мы просто добавили собаку в список кошек ... кошек [0] .Speak (); // Уоф!
Хорошо, собака, мои кошки, это нехорошо.
Функция, которую вы хотите, называется «общей ковариацией», и она поддерживается в C # 4 для интерфейсов, которые, как известно, являются безопасными. IEnumerable & lt; T & gt;
не имеет никакого способа записи в последовательность, поэтому он безопасен.
класс Animal {public virtual void Play (IEnumerable & lt; Animal & gt; животные ) {}} class Cat: Animal {public override void Play (IEnumerable & lt; Animal & gt; животные) {}} class Program {static void Main () {Cat cat = new Cat (); cat.Play (новый список & lt; Cat & gt; ()); }}
Это будет работать в C # 4, потому что List & lt; Cat & gt;
конвертируется в IEnumerable & lt; Cat & gt;
, который можно конвертировать в IEnumerable & л; & животные триазоли
. Нельзя использовать Play IEnumerable & lt; Animal & gt;
, чтобы добавить собаку к тому, что на самом деле является списком кошек.
Это нормально. Вы не устанавливаете свой флажок или нет. Вы выбираете один, а держатель вида удерживает его. Вы можете добавить логическую переменную в объект 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);
}
});
}
}
Короче говоря, это из-за повторного использования взглядов и их использования!
как вы можете этого избежать:
1. В onBindViewHolder
проверьте, следует ли вам проверять или снимать галочку коробки. не забудьте поставить оба параметра if и else
if (...)
holder.cbSelect.setChecked(true);
else
holder.cbSelect.setChecked(false);
myItems
! поэтому всякий раз, когда отображается новый вид, он читает новейшую статую объекта. Я рекомендую не использовать checkBox.setOnCheckedChangeListener
в recyclerViewAdapter
. Поскольку при прокрутке 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
}
}
});
}
У меня была та же проблема в списке 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);
}
}
(где «группа» - это объект I хотите выбрать / отменить выбор)
Просто добавьте два метода переопределения recyclerview
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}
У меня была такая же проблема. Когда я нажимал на кнопку переключения элементов в моей проверке recyclerView, кнопка Toggle появлялась в каждом 10-м элементе (например, если бы она была нажата в элементе с индексом 0, элементы с 9, 18, 27 индексами тоже нажимали). Во-первых, мой код в onBindViewHolder был:
if (newsItems.get(position).getBookmark() == 1) {
holder.getToggleButtonBookmark().setChecked(true);
}
Но затем я добавил оператор Else
if (newsItems.get(position).getBookmark() == 1) {
holder.getToggleButtonBookmark().setChecked(true);
//else statement prevents auto toggling
} else{
holder.getToggleButtonBookmark().setChecked(false);
}
И проблема была решена
Вам нужно разделить взаимодействия onBindViewHolder (логические) с CheckBox и взаимодействия с пользователем с помощью флажка. Я использовал OnCheckedChangeListener для пользовательских взаимодействий (очевидно) и ViewHolder.bind () для логики, поэтому вам нужно установить проверенный прослушиватель на нуль до настройки держателя и после того, как владелец готов - настроить проверочный прослушиватель для пользовательских взаимодействий.
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);
}
}
Хорошо, здесь много ответов, я выложу свой код, и я просто объясню, что я сделал ... это может помочь юниорам вроде меня: D.
1- Цель:
, мы создадим список RecyclerView
, который имеет CheckBox
и RadioButton
, что-то вроде этого:
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-My Amazing Adapter
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();
}
});
Я попытался использовать логическое значение в модели и сохранить статус флажка, но в моем случае это не помогло. Что для меня работало 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)). Пары вызовов могут быть вложенными , так как состояние внутренне подсчитано ». Я не знаю, как это сделать в коде, если кто-то может предоставить больше кода на этом.
Что сработало для меня, это аннулировать слушателей в viewHolder, когда представление будет переработано (onViewRecycled
):
override fun onViewRecycled(holder: AttendeeViewHolder) {
super.onViewRecycled(holder)
holder.itemView.hasArrived.setOnCheckedChangeListener(null);
holder.itemView.edit.setOnClickListener { null }
}
Вы можете использовать класс Model для отслеживания каждого элемента элемента recyclerView. Полное описание: Checkbox 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;
}
}
create 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);
}
}
}
открытый класс TagYourDiseaseAdapter расширяет RecyclerView.Adapter {private ReCyclerViewItemClickListener mRecyclerViewItemClickListener; private Контекст 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);
}
}
}
Проблема этого решения, которую я нашел, заключается в создании статического глобального массива и использовании его в классе ADAPER CLASS «onBindViewHolder», в котором я создал все глобальные переменные / объекты.
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 RVADAPTER CLASS) я дал размер массиву равным размеру / no элементов, которые я буду отображать в представлении recycler
List<Person> persons;
RVAdapter(List<Person> persons){
this.persons = persons;
PersonViewHolder.check=new int[persons.size()];
PersonViewHolder.k=persons.size();
}
BindViewHolder, I, Применил эту концепцию на кнопке, когда я нажимаю кнопку, фоновое изображение кнопки изменяется. Объект кнопки i используется как «upvote», так как «i» содержит позицию каждого элемента в представлении recycler, я использовал его как индекс массива, который работает как флаг и который отслеживает состояние элементов.
@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);
}
}
holder.cbSelect.setOnCheckedChangeListener(null);
передholder.cbSelect.setChecked(objIncome.isSelected())
– Jemshit Iskenderov 4 December 2015 в 13:21onBindViewHolder
.@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); } });
– Abbas 10 May 2016 в 04:53