Selecting one RadioButton value and scrolling back removing the selected one in RecyclerView
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.
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.
set
OnCheckedChangeListener
onRadioGroup
: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); } } });
or set
onCheckedChangeListener
on allRadioButton
s inside theRadioGroup
: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);
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.