Fernando Torres
Fernando Torres

Reputation: 470

How to avoid RadioGroup checked twice in RecyclerView

I've noticed RecyclerView "recycle" the views in the adapter but i want stop RecyclerView adapter duplicate the checked action in another item of the RecyclerView.

I have 10 items drawed into a RecyclerView, each one of them have a RadioGroup with 2 RadioButton within, but when i fired the check in the first item, for example, the number ten item have a checked too.

I was reading this question but i could'nt got it work.

Using Radio button with recyclerview in android

How to avoid this?

My adapter:

...

public class PreguntaAdapter extends RecyclerView.Adapter<PreguntaAdapter.ViewHolder> {
    private Context context;
    private ArrayList<VistaEncuestaActivity.PreguntasSiNo> preguntas;
    public ArrayList<Respuestas> respuestas = new ArrayList<Respuestas>();
    public PreguntaAdapter(Context context, ArrayList<VistaEncuestaActivity.PreguntasSiNo> preguntas) {
        this.context = context;
        this.preguntas = preguntas;
    }

    public ArrayList<Respuestas> getCheckedItems() {
        return respuestas;
    }

    @NonNull
    @Override
    public PreguntaAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        Context context = viewGroup.getContext();
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        View v = layoutInflater.inflate(R.layout.item_pregunta_sino, viewGroup, false);
        ViewHolder viewHolder = new ViewHolder(v);

        return viewHolder;
    }


    @Override
    public void onBindViewHolder(@NonNull final PreguntaAdapter.ViewHolder viewHolder, int i) {
        final VistaEncuestaActivity.PreguntasSiNo currentPregunta = preguntas.get(i);
        //viewHolder.pregunta.setText(currentEncuesta.getString_pregunta());
        viewHolder.pregunta.setText(currentPregunta.getQuestion());

        viewHolder.myLinearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        viewHolder.setIsRecyclable(false);

    }

    @Override
    public int getItemCount() {
        return preguntas.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public SharedPreferences prefs;
        private LinearLayout myLinearLayout;
        public TextView pregunta;
        public RadioGroup radio_group;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            pregunta = (TextView) itemView.findViewById(R.id.pregunta);
            radio_group = (RadioGroup) itemView.findViewById(R.id.radio_group_pregunta);
            prefs = (SharedPreferences) context.getSharedPreferences("logged", Context.MODE_PRIVATE);
            myLinearLayout = (LinearLayout) itemView.findViewById(R.id.myLinearLayout);
        }
    }
}

Upvotes: 1

Views: 994

Answers (2)

Fernando Torres
Fernando Torres

Reputation: 470

Thanks all of you for your responses. Unfortunally any response helped me to solve this issue, i used this function and i added the getItemViewType function to my adapter and it's working well now:

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

And going to the official google docs i could find the next information:

Return the view type of the item at position for the purposes of view recycling. The default implementation of this method returns 0, making the assumption of a single view type for the adapter. Unlike ListView adapters, types need not be contiguous. Consider using id resources to uniquely identify item view types. https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter

This make sense at the time RecyclerView "recycle" the views but when this is use it in the adapter this have a different behavior treating each view as unique.

Thank you to all of you.

Upvotes: 2

Jarvis
Jarvis

Reputation: 402

RadioGroup.getCheckedRadioButtonId() is the way to go. In conjunction with a SparseArray<Integer>.

In onBindViewHolder(): On each RadioGroup, set a RadioGroup.OnCheckedChangeListener(). Add the checked state to the a SparseArray or Map<Integer,Integer> mapping the index of the item position to the updated value in RadioGroup.OnCheckedChangeListener() onCheckedChanged.

So your onBindViewHolder would look something like this:

private SparseArray<Integer> mMapping = new SparseArray<>();

public void onBindViewHolder(@NonNull final PreguntaAdapter.ViewHolder viewHolder,final int position) {
        final VistaEncuestaActivity.PreguntasSiNo currentPregunta = preguntas.get(i);
        //viewHolder.pregunta.setText(currentEncuesta.getString_pregunta());
        viewHolder.pregunta.setText(currentPregunta.getQuestion());

        viewHolder.myLinearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        viewHolder.radio_group.setOnCheckedChangeListener(new OnCheckedChangeListener(){
           void onCheckedChanged(RadioGroup group,int checked) {
          mMapping.put(position,checked);
     }
}};

       // Check to see if a previous checked value exists and restore.
        if(mMapping.get(position) != null && mMapping.get(position) != -1){
           radio_group.check(mMapping.get(position));
}

        viewHolder.setIsRecyclable(false);

    }


onCheckedChanged(RadioGroup group, int checkedId)

You should give each RadioButton a unique ID, like radioButton_1, radioButton_2 in your layout file.

Upvotes: 0

Related Questions