Single selection in RecyclerView

Solution 1:

The solution for the issue:

public class yourRecyclerViewAdapter extends RecyclerView.Adapter<yourRecyclerViewAdapter.yourViewHolder> {

    private static CheckBox lastChecked = null;
    private static int lastCheckedPos = 0;


    public void onBindViewHolder(ViewHolder holder, final int position) {
    
        holder.mTextView.setText(fonts.get(position).getName());
        holder.checkBox.setChecked(fonts.get(position).isSelected());
        holder.checkBox.setTag(new Integer(position));

        //for default check in first item
        if(position == 0 && fonts.get(0).isSelected() && holder.checkBox.isChecked())
        {
           lastChecked = holder.checkBox;
           lastCheckedPos = 0;
        }
           
        holder.checkBox.setOnClickListener(new View.OnClickListener() 
        {
            @Override
            public void onClick(View v) 
            {
               CheckBox cb = (CheckBox)v;
               int clickedPos = ((Integer)cb.getTag()).intValue(); 

               if(cb.isChecked())
               {
                  if(lastChecked != null)
                  {
                      lastChecked.setChecked(false);
                      fonts.get(lastCheckedPos).setSelected(false);
                  }                       
                 
                  lastChecked = cb;
                  lastCheckedPos = clickedPos;
              }
              else
                 lastChecked = null;

              fonts.get(clickedPos).setSelected(cb.isChecked);
           }
       });
    }
}

Solution 2:

It's quite late, but I'm still posting it as it may help someone else.

Use the code below as a reference to check a single item in RecyclerView:

/**
 * Created by subrahmanyam on 28-01-2016, 04:02 PM.
 */
public class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.ViewHolder> {

    private final String[] list;
    private int lastCheckedPosition = -1;

    public SampleAdapter(String[] list) {
        this.list = list;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(parent.getContext(), R.layout.sample_layout, null);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.choiceName.setText(list[position]);
        holder.radioButton.setChecked(position == lastCheckedPosition);
    }

    @Override
    public int getItemCount() {
        return list.length;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        @Bind(R.id.choice_name)
        TextView choiceName;
        @Bind(R.id.choice_select)
        RadioButton radioButton;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            radioButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int copyOfLastCheckedPosition = lastCheckedPosition;
            lastCheckedPosition = getAdapterPosition();
            notifyItemChanged(copyOfLastCheckedPosition);
            notifyItemChanged(lastCheckedPosition);

                }
            });
        }
    }
}

Solution 3:

This is how it looks:

Single selection recyclerview best way

Inside your Adapter:

private int selectedPosition = -1;

And onBindViewHolder

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {

    if (selectedPosition == position) {
        holder.itemView.setSelected(true); //using selector drawable
        holder.tvText.setTextColor(ContextCompat.getColor(holder.tvText.getContext(),R.color.white));
    } else {
        holder.itemView.setSelected(false);
        holder.tvText.setTextColor(ContextCompat.getColor(holder.tvText.getContext(),R.color.black));
    }

    holder.itemView.setOnClickListener(v -> {
        if (selectedPosition >= 0)
            notifyItemChanged(selectedPosition);
        selectedPosition = holder.getAdapterPosition();
        notifyItemChanged(selectedPosition);
    });
}

that’s it!

As you can see, I am just notifying (updating) the previous selected item and newly selected item.

My Drawable set it as a background for recyclerview child views:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="false" android:state_selected="true">
    <shape android:shape="rectangle">
        <solid android:color="@color/blue" />
    </shape>
</item>

Solution 4:

Default value:

 private int mCheckedPostion = -1;

Just use mCheckedPosition to save the status:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

    holder.checkBox.setChecked(position == mCheckedPostion);
    holder.checkBox.setOnClickListener(v -> {
        if (position == mCheckedPostion) {
            holder.checkBox.setChecked(false);
            mCheckedPostion = -1;
        }
        else {
            mCheckedPostion = position;
            notifyDataSetChanged();
        }
    });
}