问题
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);
}
}
}
回答1:
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());
回答2:
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();
}
}
回答3:
this is what I did. In my onBindViewHolder
if(visualScore[position] == 1 ){
holder.rg.check(R.id.rb_1);
}else{
if(audioScore[position] == 1){
holder.rg.check(R.id.rb_2);
}else{
if(kinestScore[position] == 1){
holder.rg.check(R.id.rb_3);
}else{
holder.rg.clearCheck();
}
}
}
holder.rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
switch (checkedId) {
case (R.id.rb_1):
visualScore[position] = 1;
audioScore[position] = 0;
kinestScore[position] = 0;
break;
case (R.id.rb_2):
visualScore[position] = 0;
audioScore[position] = 1;
kinestScore[position] = 0;
break;
case (R.id.rb_3):
visualScore[position] = 0;
audioScore[position] = 0;
kinestScore[position] = 1;
break;
}
});
I declared all the score arrays as private global methods in the adapter class. Then, when submit button is clicked :
int v = 0, a = 0, k = 0;
for (int i = 0; i < Questions.length; i++){
v += visualScore[i];
a += audioScore[i];
k += kinestScore[i];
}
来源:https://stackoverflow.com/questions/33476951/radiogroup-in-recyclerview