24

In my application am displaying 20 multiple choice questions with the help of RecyclerView.

If I change the value of first RadioGroup and scrolls down, again scrolls up removing the selected value in RecycelarView and also i want to use that selected RadioButton value further, I was also checked link1 but i did't understood what he is doing.

Here is my sample code snippet let me know if you need any clarification.

    package com.testing.survey;

import java.util.List;

import android.annotation.SuppressLint;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;

@SuppressWarnings("rawtypes")
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {

    private List<Student> stList;

    public DataAdapter(List<Student> students) {
        this.stList = students;
    }

    // Create new views
    @Override
    public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
            int viewType) {
        // create a new view
        View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.list_row, null);

        // create ViewHolder

        ViewHolder viewHolder = new ViewHolder(itemLayoutView);

        return viewHolder;
    }

    @SuppressLint("UseValueOf") @Override
    public void onBindViewHolder(ViewHolder viewHolder,int position) {

        final int pos = position;

        viewHolder.tvQuestionNumber.setText(stList.get(position).getQuestionNumber());

        viewHolder.tvQuestion.setText(stList.get(position).getQuestion());

        viewHolder.rbAns1.setText(stList.get(position).getAnswer1());

        viewHolder.rbAns2.setText(stList.get(position).getAnswer2());

        viewHolder.rbAns3.setText(stList.get(position).getAnswer3());

        viewHolder.rbAns4.setText(stList.get(position).getAnswer4());

        viewHolder.rbAns5.setText(stList.get(position).getAnswer4());

        //viewHolder.rgAnswers.clearCheck();

        viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());
        viewHolder.rgAnswers.setTag(new Integer(position));


        Log.v("select"+position,stList.get(position).getSelectedRadioButtonId()+"");

        viewHolder.rgAnswers.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // TODO Auto-generated method stub
                int radioButtonID = group.getCheckedRadioButtonId();
                View radioButton = group.findViewById(radioButtonID);
                int clickedPos = ((Integer)group.getTag()).intValue(); 

                //Student contact=(Student)group.getTag();

                //contact.setSelectedRadioButtonId(radioButtonID);
                stList.get(clickedPos).setSelectedRadioButtonId(radioButtonID);


                Log.v("hello"+clickedPos,stList.get(clickedPos).getSelectedRadioButtonId()+"");
            }
        });

    }

    // Return the size arraylist
    @Override
    public int getItemCount() {
        return stList.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView tvQuestionNumber;
        public TextView tvQuestion;

        public RadioGroup rgAnswers;
        public RadioButton rbAns1,rbAns2,rbAns3,rbAns4,rbAns5;

        public Student singlestudent;

        public ViewHolder(View itemLayoutView) {
            super(itemLayoutView);

            tvQuestionNumber = (TextView) itemLayoutView.findViewById(R.id.tvQuestionNumber);

            tvQuestion = (TextView) itemLayoutView.findViewById(R.id.tvQuestion);
            rgAnswers=(RadioGroup)itemLayoutView.findViewById(R.id.rgAnswers);
            rbAns1=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer1);
            rbAns2=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer2);
            rbAns3=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer3);
            rbAns4=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer4);
            rbAns5=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer5);

        }

    }

    // method to access in activity after updating selection
    public List<Student> getStudentist() {
        return stList;
    }

}
Community
  • 1
  • 1
Bala Saikrupa Puram
  • 721
  • 1
  • 7
  • 28

10 Answers10

7

This problem occurs because of a bug in either RecyclerView or somewhere in the Android SDK. Anyway, I took the advice from another SO question - onCheckedChanged called automatically.

For RadioGroup, it will be a little different. There are two ways to go about. I recommend 1st one since it is plug-n-play.

  1. set OnCheckedChangeListener on RadioGroup:

    mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            if(checkedId == -1) {
                Log.v("onCheck", "Android bug since RadioButton doesn't get unchecked normally!");
            }
            else {
                Log.v("onCheck", "Valid click. By user");
                mMyListObjectArr[position].setChecked(checkedId);
            }
        }
    });
    
  2. or set onCheckedChangeListener on all RadioButtons inside the RadioGroup:

    CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if(buttonView.isPressed()) {
                Log.v("onCheck", position + ", valid click by user");
                mMyListObjectArr[position].setChecked(buttonView.getId());
            }
            else {
                Log.v("onCheck", "Android bug");
            }
        }
    };
    mRadioButton1.setOnCheckedChangeListener(onCheckedChangeListener);
    mRadioButton2.setOnCheckedChangeListener(onCheckedChangeListener);
    
Community
  • 1
  • 1
Sufian
  • 6,405
  • 16
  • 66
  • 120
  • hmmm what is `mMyListObjectArr[position]` I tried to use my `private List mExam;` e.g `mExam[position].setChecked(buttonView.getId()); ` but it says array expected, found List. How can I arrive to it being an array? – Woppi Feb 22 '17 at 12:24
  • @Woppi just as it says, you're providing a `List` where it is expecting an array. – Sufian Feb 22 '17 at 13:59
  • @Woppi as you know item from array can be get using `anArray[position]`, while item from `List` can be obtained using `aList.get(position)`. You'd do similar in here. And `mMyListObjectArr` is the list of objects that you're showing in the `RecyclerView`. So basically it is `List stList` in the OP's question. – Sufian Feb 22 '17 at 14:04
6

Modify your onBindViewHolder() to this

public void onBindViewHolder(ViewHolder viewHolder, int position) {

        final int pos = position;

        viewHolder.tvQuestionNumber.setText(stList.get(position).getQuestionNumber() + "");

        viewHolder.tvQuestion.setText(stList.get(position).getQuestion());

        viewHolder.rbAns1.setText(stList.get(position).getAnswer1());

        viewHolder.rbAns2.setText(stList.get(position).getAnswer2());

        viewHolder.rbAns3.setText(stList.get(position).getAnswer3());

        viewHolder.rbAns4.setText(stList.get(position).getAnswer4());

        viewHolder.rbAns5.setText(stList.get(position).getAnswer5());

        //viewHolder.rgAnswers.clearCheck();

        viewHolder.rgAnswers.setTag(position);


        Log.v("select" + position, stList.get(position).getSelectedRadioButtonId() + "");

        viewHolder.rgAnswers.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // TODO Auto-generated method stub
                int radioButtonID = group.getCheckedRadioButtonId();
                View radioButton = group.findViewById(radioButtonID);
                int clickedPos = (Integer) group.getTag();


               stList.get(clickedPos).setSelectedRadioButtonId(radioButtonID);

               // if you want to get selected button's info such as tag, text... etc.
                RadioButton radioButton = (RadioButton) viewHolder.itemView.findViewById(radioButtonID);

                if(radioButton != null) {
                    String customTag = radioButton.getTag().toString();
                    stList.get(clickedPos).setCustomTag(customTag);
                }


                Log.v("hello" + clickedPos, stList.get(clickedPos).getSelectedRadioButtonId() + "");
            }
        });

        viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());

    }

It should work. If any issues please let me know.

Woppi
  • 5,303
  • 11
  • 57
  • 81
Nigam Patro
  • 2,760
  • 1
  • 18
  • 33
  • I can't thank you enough! This worked for me. You saved the day! :) – Woppi Feb 22 '17 at 10:34
  • In here, how can I get the tag of specific radio button. I am getting `android.widget.RadioButton.getText()' on a null object reference` when I tried `RadioButton rb=(RadioButton) viewHolder.rgAnswers.findViewById(radioButtonID);` Log.d("TRACE", "radio button id" + radioButton.getText()); – Woppi Feb 22 '17 at 11:12
  • 1
    `viewHolder.itemView.findViewById(radioButtonID)` , like this you need to do. – Nigam Patro Feb 22 '17 at 11:26
  • hmmmm same error. This error does not appear when I get tag or text from viewholder. When I moved the listener to onBindViewHolder to resolve the recycler view checked state issue... it's returning null reference. Here is my code: https://gist.github.com/arvi/42d0922bc994e240c6190e30fb1882e3 – Woppi Feb 22 '17 at 11:42
  • Can you once try with `group.findViewById()`? – Nigam Patro Feb 22 '17 at 11:55
  • Hmmm did that too but same error `RadioButton radioButton = (RadioButton) group.findViewById(radioButtonID); Log.d("TRACE", radioButton.getText().toString());` – Woppi Feb 22 '17 at 12:02
  • Only when I comment `itemViewHolder.radioGroupPossibleAnswers.check(mExam.get(position).getSelectedRadioButtonId());` it will not produce that error... but then the recyclerview "checked" bug is back. – Woppi Feb 22 '17 at 12:03
  • But, is that needed to print log message? Without that, isn't it possible? – Nigam Patro Feb 22 '17 at 12:26
  • hmmm, what I wanted, is when I clicked on the radio button I can get the tag of that button so I can compare if answer is correct. adding the `itemViewHolder.radioGroupPossibleAnswers.check(mExam.get(pos‌​ition).getSelectedRa‌​dioButtonId());` seems to make the getTag, getText point to null reference... hmmm I'm still debugging and tracing what could be the issue... so for that is what I observed – Woppi Feb 22 '17 at 12:29
  • Will tell tomorrow. Because, I am in office and can't move to this. I also need to debug. – Nigam Patro Feb 22 '17 at 13:11
  • finally solved it... make sure to check for null and not dynamically set id of button programmatically. Once I did that.... damn it worked! Thanks a lot. I'll edit your answer to add getting of tags. – Woppi Feb 22 '17 at 15:34
5

I created a sample code that will work as per your req.

First we have to create the xml as follows :

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerViewAppList"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</LinearLayout>

Then we will create an interface as follows

public interface OnOptionSelected {
public void onOptionSelected(int position,int itemSelected);
}

Then we will create the model class as follows :

public class QuestionModel {

private String question;
private int seleectedAnswerPosition;
private boolean op1Sel,op2Sel,op3Sel; // options 

public boolean isOp1Sel() {
    return op1Sel;
   }

public void setOp1Sel(boolean op1Sel) {
    this.op1Sel = op1Sel;
    if(op1Sel){ // To make sure only one option is selected at a time
        setOp2Sel(false);
        setOp3Sel(false);
    }
   }

    public boolean isOp2Sel() {
      return op2Sel;
   }

   public void setOp2Sel(boolean op2Sel) {
    this.op2Sel = op2Sel;
    if(op2Sel){
        setOp1Sel(false);
        setOp3Sel(false);
     }
      }

 public boolean isOp3Sel() {
    return op3Sel;
     }

 public void setOp3Sel(boolean op3Sel) {
    this.op3Sel = op3Sel;
    if(op3Sel){
        setOp2Sel(false);
        setOp1Sel(false);
     }
    }

    public int getSeleectedAnswerPosition() {
    return seleectedAnswerPosition;
    }

  public void setSeleectedAnswerPosition(int seleectedAnswerPosition) {
    this.seleectedAnswerPosition = seleectedAnswerPosition;
   }

  public String getQuestion() {
    return question;
  }
 public void setQuestion(String question) {
    this.question = question;
  }
     } 

Then we will create the view for row :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/question"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

    <RadioButton
        android:id="@+id/radoptionOne"
        android:text="May Be"
        android:checked="false"
        android:saveEnabled="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <RadioButton
        android:checked="false"
        android:id="@+id/radoptionTwo"
        android:text="NO"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <RadioButton
        android:checked="false"
        android:id="@+id/radoptionThree"
        android:text="Yes"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
   </LinearLayout>

Adapter class as follows:

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

   private List<QuestionModel> questionModels;


public void setOnOptionSelected(OnOptionSelected onOptionSelected) {
    this.onOptionSelected = onOptionSelected;
}

private OnOptionSelected onOptionSelected;


public List<QuestionModel> getQuestionModels() {
    return questionModels;
}

public void setQuestionModels(List<QuestionModel> questionModels) {
    this.questionModels = questionModels;
}

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    TextView question;
    RadioGroup radioGroup;
    RadioButton op1, op2, op3;

    ViewHolder(View view) {
        super(view);
        question = (TextView) view.findViewById(R.id.question);
        //radioGroup=(RadioGroup)view.findViewById(R.id.radGroup);
        op1 = (RadioButton) view.findViewById(R.id.radoptionOne);
        op2 = (RadioButton) view.findViewById(R.id.radoptionTwo);
        op3 = (RadioButton) view.findViewById(R.id.radoptionThree);
        op1.setOnClickListener(this);
        op2.setOnClickListener(this);
        op3.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.radoptionOne:
                onOptionSelected.onOptionSelected(getAdapterPosition(), 1);
                break;

            case R.id.radoptionTwo:
                onOptionSelected.onOptionSelected(getAdapterPosition(), 2);
                break;

            case R.id.radoptionThree:
                onOptionSelected.onOptionSelected(getAdapterPosition(), 3);
                break;
        }
    }
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v;
    // create a normal view
    v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.row_view, parent, false);
    return new ViewHolder(v);

}

@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
    viewHolder.question.setText(questionModels.get(position).getQuestion());

    Log.e("POSITION" + position, "1" + questionModels.get(position).isOp1Sel());

    Log.e("POSITION" + position, "2" + questionModels.get(position).isOp2Sel());
    Log.e("POSITION" + position, "3" + questionModels.get(position).isOp3Sel());


    viewHolder.op1.setChecked(questionModels.get(position).isOp1Sel());
    viewHolder.op2.setChecked(questionModels.get(position).isOp2Sel());
    viewHolder.op3.setChecked(questionModels.get(position).isOp3Sel());


}

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

Then the Activity class :

public class MainActivity extends Activity implements OnOptionSelected{

private RecyclerView mRecyclerView;
private List<QuestionModel> questionModels;
private  QuestionAdapter questionAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mRecyclerView =(RecyclerView)findViewById(R.id.recyclerViewAppList);
    mRecyclerView.setHasFixedSize(true);
    questionModels=new ArrayList<QuestionModel>();
    for (int i=0;i<20;i++)
    {
        QuestionModel questionModel=new QuestionModel();
        questionModel.setQuestion("Question " + (i + 1));
        questionModels.add(questionModel);
    }
    questionAdapter =new QuestionAdapter();
    questionAdapter.setOnOptionSelected(this);
    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    questionAdapter.setQuestionModels(questionModels);
    mRecyclerView.setLayoutManager(layoutManager);
    mRecyclerView.setAdapter(questionAdapter);
}


@Override
public void onOptionSelected(int position, int itemSelected) {
    questionModels.get(position).setSeleectedAnswerPosition(itemSelected);
    switch (itemSelected){
        case 1:
            questionModels.get(position).setOp1Sel(true);
            break;

        case 2:
            questionModels.get(position).setOp2Sel(true);
            break;
        case 3:
            ((QuestionModel)questionModels.get(position)).setOp3Sel(true);
            break;
    }
    questionAdapter.setQuestionModels(questionModels);
    questionAdapter.notifyDataSetChanged();
   // mRecyclerView.setAdapter(questionAdapter);

}
 }

I tried the solution with Radiogroup but it was not working properly( sometime it was retaining the old value). Then I changed the way of the selecting options in my model class.

sample

avinash
  • 1,744
  • 24
  • 40
4

You can do it in this way.....

inside your bean class add one field say

String final_answer;
public String getFinalAnswer(){
  return final_answer;
}

public void setFinalAnswer(String final_answer){
  this.final_answer = final_answer;
}

in adapter.....

public void onBindViewHolder(final ViewHolder viewHolder, final int position) {

    final Student student = stList.get(position);

    viewHolder.tvQuestionNumber.setText(student.getQuestionNumber());

    viewHolder.tvQuestion.setText(student.getQuestion());

    viewHolder.rbAns1.setText(student.getAnswer1());

    viewHolder.rbAns2.setText(student.getAnswer2());

    viewHolder.rbAns3.setText(student.getAnswer3());

    viewHolder.rbAns4.setText(student.getAnswer4());

    viewHolder.rbAns5.setText(student.getAnswer4());

    viewHolder.rgAnswers.clearCheck();

   if(student.getSelectedRadioButtonId()!=null)
     viewHolder.rgAnswers.check(student.getSelectedRadioButtonId());
   else
     viewHolder.rgAnswers.clearCheck();

    viewHolder.rgAnswers.setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
          if(checkedId != -1){
            student.setSelectedRadioButtonId(checkedId);
            RadioButton rb = (RadioButton)viewHolder.rgAnswers.
                                  findViewById(checkedId);

            student.setFinalAnswer(rb.getText);
            stList.get(position) = student;
          }
        }
    });
}

To get selected answers finally...write this code in main activity

  public void getSelectedAnswers(){

       for(int i=0;i<slist.length;i++){
          //get selected answer
          Log.i("answer",slist.get(i).getFinalAnswer());
       }
    }
H Raval
  • 1,903
  • 17
  • 39
  • there is a problem in this if i scroll down the 7 the and 8 answers are automatically selecting based on 1 st and 2 nd, how can we fix this. and am also sharing the git link you can check the code there. https://github.com/saikrupa/Survay – Bala Saikrupa Puram Dec 18 '15 at 01:33
  • 1
    but not every time it's selecting some times only i was changed only 1 line of text from your present code i.e (`stList.get(position).add(student);`) instead of `stList.get(position) = student;` and i was also added to master class `public void add(Student student) { this.setSelectedRadioButtonId(student.getSelectedRadioButtonId()); }` – Bala Saikrupa Puram Dec 18 '15 at 01:55
0

The problem is that the recycler view is recycling (like the name says) your views.

The system creates a certain amount of ViewHolders to fill your screen after reaching that amount it reuses the already existent ViewHolders.

If you set the button checked in your first listentry and it reuses the ViewHolder for your 7th listentry the button is still checked(because it got set in the ViewHolder).

To fix this problem you need to set the default appearance for your listentries in onBindViewHOlder every time.

Update:

public void onBindViewHolder(final ViewHolder viewHolder, final int position) {

    final Student student = stList.get(position);

    viewHolder.tvQuestionNumber.setText(student.getQuestionNumber());

    viewHolder.tvQuestion.setText(student.getQuestion());

    viewHolder.rbAns1.setText(student.getAnswer1());

    viewHolder.rbAns2.setText(student.getAnswer2());

    viewHolder.rbAns3.setText(student.getAnswer3());

    viewHolder.rbAns4.setText(student.getAnswer4());

    viewHolder.rbAns5.setText(student.getAnswer4());

    viewHolder.rgAnswers.clearCheck();

    viewHolder.rgAnswers.check(student.getSelectedRadioButtonId());

    viewHolder.rgAnswers.setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            student.setSelectedRadioButtonId(checkedId);
            Log.v("hello"+position,checkedId+"");
        }
    });
}

I slightly updated your new approach, maybe this helps ?

Oliver
  • 503
  • 1
  • 3
  • 13
  • I'm not sure how this will help, you're setting all the buttons to not checked. What if a user checks one scrolls down and then back up, you would need to reset the original checked state instead of unchecking them all. Furthur, what are you doing with `setTag()` looking at the doc it seems completely unrelated: http://developer.android.com/intl/ru/reference/android/view/View.html#setTag(int, java.lang.Object) – Charles Durham Dec 16 '15 at 02:18
  • i was changes my code in the above way please have a look on it am sill getting the same problem – Bala Saikrupa Puram Dec 16 '15 at 09:26
  • I updated my anwser once more, if you still have problems it would be nice if you could provide more information about the problem (e.g. a screenshot). – Oliver Dec 16 '15 at 10:09
  • upVoted but the answer is not usefull once check the code which is edited – Bala Saikrupa Puram Dec 17 '15 at 04:12
0

In your model class add

private int checkedId = -1;

public int getCheckedId() {
    return checkedId;
}

public void setCheckedId(int checkedId) {
    this.checkedId = checkedId;
}

and change onBindViewHolder in adapter like this:

 @Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
    viewHolder.tvQuestion.setText(stList.get(position).getQuestion());

    viewHolder.rbAns1.setText(stList.get(position).getAnswer1());
    viewHolder.rbAns2.setText(stList.get(position).getAnswer2());
    viewHolder.rbAns3.setText(stList.get(position).getAnswer3());
    viewHolder.rbAns4.setText(stList.get(position).getAnswer4());
    viewHolder.rbAns5.setText(stList.get(position).getAnswer5());

    viewHolder.radGrp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(RadioGroup rgp, int checkedId) {
            // TODO Auto-generated method stub
            stList.get(position).setCheckedId(rgp.getCheckedRadioButtonId());
        }
    });

    viewHolder.radGrp.check(stList.get(position).getCheckedId());
}
Srikanth
  • 1,555
  • 12
  • 20
0

As i have seen your code...

just add single line

viewHolder.rgAnswers.setOnCheckedChangeListener(null);

in onBindViewHolder() method above of this line

viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId()); ...

if it solved your problem ..let me know ... i will explain you a scenario why its happening .. Because i faced similer problem and solved using this solution.

Moinkhan
  • 12,732
  • 5
  • 48
  • 65
0

Inside your student class add a boolean variable isSelected. Now on checkedChangeListener of each radiogroup, change the value of isSelected to mark whether some value has been selected or no selection has been made. Now inside onBindViewHolder() just do

    if(stList.get(position).isSelected){
  viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());
    }else{
    viewHolder.rgAnswers.clearCheck();
    }

At the end you can iterate over the whole list and check for which objects, isSelected is true

Ankit Aggarwal
  • 5,317
  • 2
  • 30
  • 53
0

RecyclerView came over ListView and its major property that is It Reuses cells while scrolling up and down. Due to this it do not flick while scrolling even if you have lots of data in your list. You are getting problem due to Reuse of cells in RecyclerView.

You can overcome to this problem by binding your RecyclerView list data to Modal class with getter and setter method. You can display checkbox checked or unchecked on basis of cell position and corresponding data. In my sample i used setOnClickListener instead of setOnCheckedChangeListenerto to show checkbox checked or unchecked.

Anuj Sharma
  • 4,294
  • 2
  • 37
  • 53
0

Well the main problematic piece of code which most of developer does that re register listener again and again.

  • So first important point not to register listener in onBindViewHolder
  • And second important point to get it resolve by setting tag in efficient way, hence not to save big object in tag so we will only save position.

In my case I am having four radio buttons in a group which lies in a list_item layout:

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val question = questions[position]
        holder.questionNumberTextView.text = "" + question.id + "."
        holder.questionTextView.text = question.question
        holder.myRadioGroup.tag = position
        if (question.selectedRadioButtonId != -1) {
            holder.myRadioGroup.check(question.selectedRadioButtonId);
        } else {
            //your always need to write else condition
            holder.myRadioGroup.clearCheck();
        }
}
 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    var itemLayoutView = LayoutInflater.from(parent.context)
        .inflate(R.layout.list_item, parent, false)

    val myViewHolder = MyViewHolder(itemLayoutView)
    myViewHolder.myRadioGroup.setOnCheckedChangeListener { radioGroup, radioButtonId ->
        val clickedPos = radioGroup.tag as Int
        Log.i("MyAdapter", "clicked pos:: $clickedPos  radioButtonId :: $radioButtonId")
        questions[clickedPos].selectedRadioButtonId = radioButtonId
    }
    return myViewHolder
}

enter image description here

Min2
  • 10,751
  • 2
  • 19
  • 22