RecyclerView में चेकबॉक्स विभिन्न वस्तुओं की जाँच करता रहता है


94

यहाँ 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 देखें। यह स्क्रॉल करते समय स्थिति को बचाने में मदद करता है।
विटाली

जवाबों:


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);
            }
        });

    }
}

20
यह काम नहीं किया। आपको holder.cbSelect.setOnCheckedChangeListener(null);पहले लिखना होगाholder.cbSelect.setChecked(objIncome.isSelected())
Jemshit Iskenderov

2
वहाँ किसी भी कारण के रूप में क्यों स्थापित करने के लिए धारक है ।.cbSelect.setOnCheckedChangeListener (नल); काम करता है?
डेब

4
@oguzhand हाय मैंने आपके समाधान की कोशिश की, लेकिन इसके काम नहीं कर रहा है: श्रोता को शून्य करने के लिए या उसके बिना।
अब्बास

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
@ अगर आपको किसी ऑब्जेक्ट में चेकबॉक्स स्थिति रखने की आवश्यकता है, तो देखें, क्योंकि ViewHolder एक धारक है। यदि आपके पास 100 आइटम हैं, तो आपके पास केवल 6-7 (स्क्रीन और लेआउट आकार पर निर्भर करता है) ViewHolders हैं और एक चक्र में इन सभी वस्तुओं का उपयोग करते हैं।
औज़ुहान डोंगल

22

संक्षेप में, इसकी वजह से विचारों को पुनर्चक्रण करना और उनका फिर से उपयोग करना है!

आप इससे कैसे बच सकते हैं:

1. onBindViewHolderजाँच करें कि क्या आपको बक्से को चेक या अनचेक करना चाहिए। अगर और नहीं तो दोनों रखना मत भूलना

if (...)
    holder.cbSelect.setChecked(true);
else
    holder.cbSelect.setChecked(false);
  1. चेक बॉक्स के लिए एक श्रोता रखो! जब भी इसकी जाँच की गई प्रतिमाएँ बदली गई हैं, तो इसी वस्तु को अपने myItemsऐरे में भी अपडेट करें इसलिए जब भी कोई नया दृश्य दिखाया जाता है, तो वह ऑब्जेक्ट की नवीनतम प्रतिमा को पढ़ता है।

आपका दूसरा बिंदु कुंजी था। यद्यपि यह एक स्थिति में सबसे अच्छा काम करता है, जब प्रारंभिक डेटासेट में चेक किए गए राज्य (जो मेरे लिए मामला है) के बारे में जानकारी है
Attila Orosz

1
यह अधिक सीधा-सीधा और सही उत्तर है। BOTH के लिए सेट-चेक सही और गलत onBindViewHolder कुंजी है
Jk

मेरे मामले में, मुझे isChecked falseशुरू में निर्धारित सभी डेटा के लिए डेटा मॉडल में डिफ़ॉल्ट मूल्य के साथ डेटा को सहेजना होगा , फिर onCheckChangedमैंने बस isCheckedमूल्य को अपडेट किया trueया falseजैसा कि उत्तर कार्यान्वयन में बताया गया है कि चेक या तो चेक किया गया है या नहीं।
अली तमूर

20

केवल तभी उपयोग करें जब आप अपने RECECCLER VIEW में सीमित संख्या में हैं।
मैंने मॉडल में बूलियन मूल्य का उपयोग करने की कोशिश की और चेकबॉक्स की स्थिति बनाए रखी, लेकिन इससे मेरे मामले में मदद नहीं मिली। मेरे लिए जो काम किया गया है, वह यह है। इट्सइसाइक्लेबल (झूठा);

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 ()

नोट: यह एक समाधान है। इसे ठीक से उपयोग करने के लिए आप उस दस्तावेज़ का उल्लेख कर सकते हैं जिसमें कहा गया है "कॉल टू सेटिसेक्लेबल () को हमेशा युग्मित किया जाना चाहिए (सेटआईएस साइक्लेबेबे (झूठा) के लिए एक कॉल को हमेशा सेटिस्काइक्लेबल (सच)) के बाद के कॉल के साथ मिलान किया जाना चाहिए। कॉल के जोड़े नेस्टेड हो सकते हैं। , जैसा कि राज्य में आंतरिक रूप से संदर्भ-गणना है। " मुझे नहीं पता कि कोड में यह कैसे करना है, अगर कोई इस पर अधिक कोड प्रदान कर सकता है।


आप इसे कैसे उपयोग करने के लिए समझा सकते हैं?
UserName_Untold

44
यह recyclerView के पीछे तर्क की बर्बादी नहीं है?
एरेन

3
मैंने इसे लंबी सूची के साथ आज़माया, जिसने यादृच्छिक जाँच के मुद्दे को हल किया लेकिन जब मैं नीचे स्क्रॉल करता हूं और लंबी सूची के साथ फिर से स्क्रॉल करता हूं, तो चेक किए गए चेकबॉक्स गायब हो जाते हैं :(
सोनडांग

2
यह दृश्य को अप्राप्य बनाने के लिए एक अच्छा विचार नहीं है क्योंकि यह स्मृति को सूखा देगा और आप पुनर्नवीनीकरण दृश्य के अधिकांश लाभों को खो देंगे।
आर्थर

मैं आप लोगों से सहमत हूँ, @ eren130 और आर्थर। मैंने पोस्ट को संपादित किया है, और अगर हम setIsyclable (सही या गलत) का उपयोग करने के तरीके के साथ आ सकते हैं तो बहुत सराहना करेंगे; अच्छी तरह।
राणा रणविजय सिंह

16

बस के दो ओवरराइड विधियों को जोड़ें RecyclerView

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

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

2
ऐसा मत करो !! यह recyclerView रीसाइक्लिंग तंत्र को बायपास करेगा और इसका उपयोग करने के पूरे बिंदु को खो देगा।
हनोक मोरेनो

1
नहीं, यह नहीं होगा, यह दृश्य धारक में हर पुनर्नवीनीकरण दृश्य की सटीक स्थिति देता है।
हरीश रेड्डी

1
हरीश, शायद मुझे कुछ याद आ रहा है, लेकिन जहां तक ​​मुझे पता है, ऐसा करने से आप वास्तव में एडॉप्टर को बता सकते हैं कि आइटम प्रकारों की संख्या आइटम गणना है। अभिप्राय यह है कि किसी भी वस्तु का पुनर्नवीनीकरण नहीं किया जा सकता है क्योंकि उसमें कोई सिमिलर दृश्य नहीं है। हालांकि इसका परीक्षण करना आसान है। बस onBindViewHolder के अंदर viewHolder.itemView रेफ़रेंस को लॉग इन करें और देखें कि क्या एक ही व्यू रेफ़रेंस पर दो व्यूहोल्डर्स हैं। परीक्षण एक लंबी सूची पर होना चाहिए ताकि रीसाइक्लिंग प्रणाली निष्पादित हो जाएगी।
हनोक मोरेनो

3
यह निर्दोष रूप से जाग गया, इसने मेरा दिन बचा लिया।
कुंदन

5
यदि आपके पास अपने रिसाइकलव्यू में 100 से अधिक आइटम हैं, तो यह समाधान एक ही बार में सभी आइटमों को लोड कर देगा, इससे आपको आउटऑममोरीएक्ससेप्शन हो सकता है यदि आपके पास चित्र हैं, अन्यथा यह समाधान सही है @Kundan
हरीश रेड्डी

11

आप प्रत्येक पुनर्नवीनीकरण आइटम के चेकबॉक्स का ट्रैक रखने के लिए मॉडल वर्ग का उपयोग कर सकते हैं। पूर्ण संदर्भ से है: RecyclerView चेकबॉक्स Android

सेटटैग और गेटटैग का इस्तेमाल चेकबॉक्स स्टेटस पर नज़र रखने के लिए किया जाता है। अधिक जानकारी के लिए पूर्ण संदर्भ लिंक देखें। यह यह भी सिखाता है कि चेक किए गए आइटम को 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);
    }

}

}


4

कोटलिन का उपयोग केवल एक चीज है जो मेरे लिए इस समस्या को हल OnCheckedChangeListenerकरता है चर सेट करने से पहले साफ़ करना और फिर सेट OnCheckedChangeListenerहोने के बाद एक नया बनाना checked

मैं अपने में निम्नलिखित करता हूं RecyclerView.ViewHolder

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

1
यह पूरी तरह से काम कर रहा है। मैं क्यों नहीं, लेकिन यह केवल तभी काम करता है जब कोई KOTLIN का उपयोग कर रहा हो!
आदित्य एस

यह वास्तव में काम कर रहा है। उसने जो किया है वह बहुत ही चालाक और स्पष्ट है। task.setOnCheckedChangeListener(null)चेकबॉक्स को एकदम नया माना जाता है क्योंकि हम सिर्फ नई घटनाओं में ही दिलचस्पी रखते हैं। फिर बहुत चालाक।
AbdElraouf साबरी

2

मेरा सुझाव है कि उपयोग करने के लिए नहीं 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
                }

            }
        });

    }

2

जैसा कि ऊपर कहा गया है, वस्तु की जांच की गई स्थिति को वस्तु गुणों के भीतर शामिल किया जाना चाहिए। कुछ मामलों में आपको ऑब्जेक्ट पर क्लिक करके ऑब्जेक्ट चयन स्थिति को भी बदलना पड़ सकता है और चेकबॉक्स को वास्तविक स्थिति (या तो चयनित या अचयनित) के बारे में सूचित करने दें। चेकबॉक्स तब दिए गए एडॉप्टर की वास्तविक स्थिति में ऑब्जेक्ट की स्थिति का उपयोग करेगा जो सूची में तत्व की स्थिति में (डिफ़ॉल्ट रूप से / ज्यादातर मामलों में) है।

नीचे दिए गए स्निपेट की जांच करें, यह उपयोगी हो सकता है।

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

वस्तुओं की स्थिति धारण करने के लिए एक सरणी का उपयोग करें

एडेप्टर में एक मैप या एक स्पार्सबुलियनअरे का उपयोग करें (जो एक मैप के समान है, लेकिन हमारे आइटम की सूची में सभी वस्तुओं की स्थिति को स्टोर करने के लिए एक कुंजी-मूल्य जोड़ी है इंट और बूलियन) और फिर तुलना करने के लिए कुंजी और मूल्यों का उपयोग करें। चेक किए गए राज्य को टॉगल करते समय

एडाप्टर में एक बनाएँ SparseBooleanArray

// sparse boolean array for checking the state of the items

    private SparseBooleanArray itemStateArray= new SparseBooleanArray();

फिर आइटम पर क्लिक करें हैंडलर आइटम onClick()की स्थिति का उपयोग आइटम में करते हैं।

        @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

मुझे स्विचेस के साथ RecyclerView सूची में एक ही समस्या थी, और @oguzhand उत्तर का उपयोग करके इसे हल किया, लेकिन इस कोड के साथ CheckChangeListener के अंदर:

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

(जहां 'समूह' वह इकाई है जिसका चयन / चयन करना चाहता हूं)


1

आपको चेकबॉक्स के साथ onBindViewHolder (तर्क) इंटरैक्शन और चेकबॉक्स के साथ उपयोगकर्ता इंटरैक्शन को अलग करने की आवश्यकता है। मैंने तर्क के लिए उपयोगकर्ता इंटरैक्शन (जाहिर है) और ViewHolder.bind () के लिए OnCheckedChangeListener का उपयोग किया, यही कारण है कि आपको धारक को सेट करने से पहले अशक्त करने के लिए चेक श्रोता को सेट करने की आवश्यकता है और धारक तैयार होने के बाद - उपयोगकर्ता इंटरैक्शन के लिए चेक श्रोता को कॉन्फ़िगर करें।

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

इस समाधान की समस्या जो मुझे मिली, वह एक स्थिर वैश्विक सरणी बनाकर और "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 क्लास के कंस्ट्रक्टर में) मैंने सरणी को आकार दिया / पुनरावर्तक दृश्य में प्रदर्शित होने वाली वस्तुओं के आकार के बराबर / नहीं

List<Person> persons;

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

BindViewHolder, I, इस अवधारणा को एक बटन पर लागू करता है, जब मैं एक बटन पर क्लिक करता हूं, तो बटन की पृष्ठभूमि छवि बदल जाती है। मेरे द्वारा उपयोग किए जाने वाले बटन का उद्देश्य "अपवोट" के रूप में नाम है, जैसा कि "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);
        }

और समस्या हल हो गई


धन्यवाद। यदि यह एक ही दृश्य को पुनर्चक्रण करता है, तो डिफ़ॉल्ट रूप से जाँच करने पर, Else भाग चेकबॉक्स को साफ़ कर देगा।
आदर्श विजयन पी।

1

ठीक है, यहाँ बहुत सारे जवाब हैं मैं अपना कोड पोस्ट करूँगा और मैं बस समझाऊंगा कि मैंने क्या किया ... यह शायद मेरे जैसे जूनियर्स की मदद करे: डी।

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

सार्वजनिक वर्ग TagYourDiseaseAdapter RecyclerView.Adcape का विस्तार करता है {निजी 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और उसके लिए गेट्टर और सेटर सेट करें, उपरोक्त मामले में मेरा सेटचेक और आईचेक है

आशा है कि यह कुछ मदद करता है यदि ऐसा है तो + इस जवाब पर वोट करें



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

जब दृश्य पुनर्नवीनीकरण होने जा रहा हो ( onViewRecycled):

 override fun onViewRecycled(holder: AttendeeViewHolder) {
            super.onViewRecycled(holder)
            holder.itemView.hasArrived.setOnCheckedChangeListener(null);
            holder.itemView.edit.setOnClickListener { null }
        }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.