2

This is my problem: https://youtu.be/k-N5uthYhYw

and this is my onBindViewHolder() method.

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    // - get element from your dataset at this position
    // - replace the contents of the view with that element

    holder.specName.setText(specList.get(position).getSpecName());

    // Assign a tag number to later identify what radio-button
    holder.specRadioBtn.setTag(new Integer(position));

    /* Event listenr for longClick - we prob. won't use it, but it's here just in case */
    holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {

            Toast.makeText(context, "Long press", Toast.LENGTH_SHORT).show();

            return false;
        }
    });

    /* Little hack to select its Radio Button when a specific row is tapped */
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            // Turn rowSelectedFlag to true since the user selected this row
            rowSelectedFlag = true;

            // When the user taps on a row select that row's radio button
            holder.specRadioBtn.setChecked(true);

            // I'm not sure why, but locally the interface needs to be started by pointing it
            // to where it should drive the data (to send the params)
            tempInterface = new AdminUserSpecialty();

            // Call the interface to send the data (row spec-name and id) back to AdminUserSpecialty
            tempInterface.activateSpecSelect(specList.get(position).getSpecName().toString(),
                    specList.get(position).getSpecId().toString(), rowSelectedFlag);

            int clickedPos = ((Integer) holder.specRadioBtn.getTag());

            // Check if the radio button is already selected
            if (holder.specRadioBtn.isChecked()) {

                if (lastCheckedBtn != null) {

                    // Don't deselect if user taps on the same row several times
                    if (lastCheckedBtn == holder.specRadioBtn) {

                        // do nothing
                    }

                    // Otherwise do deselect the previously selected radio button
                    else {

                        lastCheckedBtn.setChecked(false);
                    }
                }

                lastCheckedBtn = holder.specRadioBtn;
                lastCheckedPos = clickedPos;
            }

            // If radio is not checked set the lastCheckedBtn to null (reset counter)
            else {
                lastCheckedBtn = null;
            }
        }
    });

    /* ----------------------------------------------------------------------*/


}

I can't seem to preserve my radio-button selection on RecyclerView scroll. On scroll the selection becomes erratic and random. I understand that one of RecyclerView's features is to recycle rows as they leave the screen, but what do I need to do to keep my selection? Thanks much.

Nactus
  • 702
  • 2
  • 13
  • 35

3 Answers3

4

I know that this was answered already but if some of you are still looking for an easier answer and your application does not rely on the RecyclerView view recycling feature much (for example if you have a fixed size list of items...) you can always set your recycler view cache view size. That way it would not recycler your views hence it would not recycler the views and you will avoid copy selected values to another views...

yourRecyclerView..setItemViewCacheSize(yourItemList.size());
Ph0b0x
  • 664
  • 7
  • 20
1

Save the checked / unchecked status of the radio button (you should use checkbox instead if you want to allow the user to select multiple items) to your model (i.e. your items in the list should have a field for this) when the onClick event happens. When you bind the ViewHolder, make sure you set checkbox's value to whatever you saved in your model.

Gergely Kőrössy
  • 5,620
  • 3
  • 28
  • 44
  • Thanks for your answer. So, if I'm not mistaken, you're suggesting that my Model Class (the data container - in this case what populates each row from my arrayList) would have a member variable that would save the state of the radio-btn (checked or unchecked)? – Nactus Aug 27 '15 at 18:44
  • Yes, that's one way to do it. If you don't want to "contaminate" your model with this extra information, you can just introduce a new array or list which holds only this property as meta data for the rows. – Gergely Kőrössy Aug 27 '15 at 20:28
1

It's happen because of the Recycling mechanism

(PS: its the same for the ListView or RecyclerView).

To fix that:

  • 1) Add a booelan variable to your model to save the state of the RadioButton

  • 2) Update your RadioButton state in onBindViewHolder() method from this boolean in the model.

  • 3) Add setOnCheckedChangeListener() to your RadioButton to listen to his state (checked/unchecked) and to update the boolean in your model when the state changes.

Community
  • 1
  • 1
Rami
  • 7,879
  • 12
  • 36
  • 66