I am having a recyclerview where each list item has a radiogroup with 4 radio buttons. How can I store the state of each radiogroup correctly. Here is my code. On scrolling up/down the states are incorrects. Thanks
public class ElementListAdapter extends RecyclerView.Adapter<ElementListAdapter.ViewHolder> {
private List<Element> elements = new ArrayList<>();
private Context context;
private int[] state;
public ElementListAdapter(Context context, List<Element> elements) {
this.context = context;
this.elements = elements;
this.state = new int[elements.size()];
Arrays.fill(this.state, -1);
}
@Override
public ElementListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_layout, parent,
false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final Element ele = elements.get(position);
final String title = ele.getTitle();
final String description = ele.getDescription();
// Set text
holder.tvTitle.setText(title);
holder.tvDesciption.setText(description);
if (ele.isHeader()) {
holder.radioGroup.setVisibility(View.GONE);
} else {
holder.radioGroup.setVisibility(View.VISIBLE);
}
setRadio(holder, this.state[position]);
holder.rb1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
state[position] = 0;
setRadio(holder, state[position]);
}
});
holder.rb2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
state[position] = 1;
setRadio(holder, state[position]);
}
});
holder.rb3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
state[position] = 2;
setRadio(holder, state[position]);
}
});
holder.rb4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
state[position] = 3;
setRadio(holder, state[position]);
}
});
}
private void setRadio(final ViewHolder holder, int selection) {
System.out.println("SELECT:" + selection);
RadioButton b1 = holder.rb1;
RadioButton b2 = holder.rb2;
RadioButton b3 = holder.rb3;
RadioButton b4 = holder.rb4;
b1.setChecked(false);
b2.setChecked(false);
b3.setChecked(false);
b4.setChecked(false);
if (selection == 0) b1.setChecked(true);
if (selection == 1) b2.setChecked(true);
if (selection == 2) b3.setChecked(true);
if (selection == 3) b4.setChecked(true);
}
@Override
public int getItemCount() {
return elements.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public View view;
public TextView tvTitle;
public TextView tvDesciption;
public RadioGroup radioGroup;
public RadioButton rb1, rb2, rb3, rb4;
public ViewHolder(View itemView) {
super(itemView);
view = itemView;
tvTitle = (TextView) itemView.findViewById(R.id.title);
tvDesciption = (TextView) itemView.findViewById(R.id.description);
radioGroup = (RadioGroup) itemView.findViewById(R.id.radioGroup);
rb1 = (RadioButton) itemView.findViewById(R.id.rb1);
rb2 = (RadioButton) itemView.findViewById(R.id.rb2);
rb3 = (RadioButton) itemView.findViewById(R.id.rb3);
rb4 = (RadioButton) itemView.findViewById(R.id.rb4);
}
}
}
The best way and the most efficient to do this is to simply add a variable which holds the option(radio button selected) to the class. And after onClick() just assign which radio button is selected to the variable and fetch that. First, add a variable in your Element class which stores the radio button option selected.
The best way saving your item state
is placing the state variable inside the item model
of the list, ex : "Element" in your case, than inside onBindViewHolder
set the state based on your model, in your case:
change this :setRadio(holder, this.state[position]);
to this : setRadio(holder, elements.get(position).getState());
and
inside onClick methods
ex: for the first one
change this:
state[position] = 0;
setRadio(holder, this.state[position]);
to this :
elements.get(position).setState(0);
setRadio(holder, elements.get(position).getState());
The best way and the most efficient to do this is to simply add a variable which holds the option(radio button selected) to the class. And after onClick() just assign which radio button is selected to the variable and fetch that.
First, add a variable in your Element class which stores the radio button option selected.
Then,
public class ElementListAdapter extends RecyclerView.Adapter<ElementListAdapter.ViewHolder> {
private List<Element> elements = new ArrayList<>();
private Context context;
//instance of interface created
final private ListItemClickListener myOnClickListener;
private int[] state;
//create a interface which helps to communicates with your main activity
public interface ListItemClickListener
{
void onListItemClick(int clickItemIndex,String optionSelected);
}
public ElementListAdapter(Context context, List<Element> elements) {
this.context = context;
this.elements = elements;
this.state = new int[elements.size()];
Arrays.fill(this.state, -1);
}
@Override
public ElementListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_layout, parent,
false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final Element ele = elements.get(position);
final String title = ele.getTitle();
final String description = ele.getDescription();
// Set text
holder.tvTitle.setText(title);
holder.tvDesciption.setText(description);
if (ele.isHeader()) {
holder.radioGroup.setVisibility(View.GONE);
} else {
holder.radioGroup.setVisibility(View.VISIBLE);
}
holder.setIsRecyclable(false);
//here you check the option selected
switch (Element.getUserOption()) {
case "1":
holder.rb1.setChecked(true);
break;
case "2":
holder.rb2.setChecked(true);
break;
case "3":
holder.rb3.setChecked(true);
break;
case "4":
holder.rb4.setChecked(true);
break;
default:
holder.radioGroup.clearCheck();
}
}
@Override
public int getItemCount() {
return elements.size();
}
//make sure to implement onClickListener here
public static class ViewHolder extends RecyclerView.ViewHolder implements View.onClickListener {
public View view;
public TextView tvTitle;
public TextView tvDesciption;
public int clickedCardPosition;
public RadioGroup radioGroup;
public RadioButton rb1, rb2, rb3, rb4;
public ViewHolder(View itemView) {
super(itemView);
view = itemView;
tvTitle = (TextView) itemView.findViewById(R.id.title);
tvDesciption = (TextView) itemView.findViewById(R.id.description);
radioGroup = (RadioGroup) itemView.findViewById(R.id.radioGroup);
rb1 = (RadioButton) itemView.findViewById(R.id.rb1);
rb2 = (RadioButton) itemView.findViewById(R.id.rb2);
rb3 = (RadioButton) itemView.findViewById(R.id.rb3);
rb4 = (RadioButton) itemView.findViewById(R.id.rb4);
rb1.setOnClickListener(this);
rb2.setOnClickListener(this);
rb3.setOnClickListener(this);
rb4.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int clickedCardPosition = getAdapterPosition();
if(rb1.isPressed()) myOnClickListener.onListItemClick(clickedCardPosition, "1");
if(rb2.isPressed()) myOnClickListener.onListItemClick(clickedCardPosition,"2");
if(rb3.isPressed()) myOnClickListener.onListItemClick(clickedCardPosition,"3");
if(rb4.isPressed()) myOnClickListener.onListItemClick(clickedCardPosition,"4");
}
}
}
Then, in your activity where you are assigning the adapter, implement the Interface.
//implement here
public class YourMainActivity extends AppCompatActivity implements
recyclerAdapter.ListItemClickListener{
.
.
.
.
.
@Override
public void onListItemClick(int clickItemIndex, String optionSelected) {
//Here assign the value to the Element Obj
yourList.get(clickItemIndex).setUserOption(optionSelected);
yourAdapter.notifyDataSetChanged();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With