Single selection in RecyclerView
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();
}
});
}
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);
}
});
}
}
}
This is how it looks:
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>
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);
}
});
}
}