Single Selection in Recyclerview

Single selection in RecyclerView

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);
}
});
}
}

Recyclerview Single Item Selector

This is my sample solution:

public class VisaTypeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

Context context;
private List<VisaType> visaTypeList;

int selected_position;


public VisaTypeAdapter(Context context, List<VisaType> visaTypeList) {
this.context = context;
this.visaTypeList = visaTypeList;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.visa_type_row, parent, false);
return new jp.workjapan.adapters.VisaTypeAdapter.ViewHolder(view);

}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
final VisaType a = visaTypeList.get(position);
final jp.workjapan.adapters.VisaTypeAdapter.ViewHolder viewHolder = (jp.workjapan.adapters.VisaTypeAdapter.ViewHolder) holder;
viewHolder.visa_eng.setText(a.getName_en());
viewHolder.visa_jp.setText(a.getName_jp());


final long id = a.getId();
if (id == AppSingleTon.visaType) {
viewHolder.visa_layout.setSelected(true);
} else {
viewHolder.visa_layout.setSelected(false);
}

if (position == selected_position) {
viewHolder.visa_layout.setSelected(true);
} else {
viewHolder.visa_layout.setSelected(false);
}

viewHolder.visa_layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selected_position = getAdapterPosition();
notifyDataSetChanged();
}
});

}

}

Hope it helps you...
Thanks

Single Selection RecyclerView TextView

I will show you how to achieve what you are looking for using a simple example to show a list of strings.

My view to represent a item in RecyclerView view will be test_cell_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/holder_background"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"/>

</LinearLayout>

And I created an adapter extending RecyclerView.Adapter

import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;


public class TestAdapter extends RecyclerView.Adapter<TestAdapter.ViewHolder> {

private int selectedPos = 0;

private OnItemClickListener listener;

public interface OnItemClickListener {
void onItemClick(View viewItem, int position);
}

public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}

public class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout background;
TextView itemText;

ViewHolder(final View viewItem) {
super(viewItem);
background = (LinearLayout) viewItem.findViewById(R.id.holder_background);
itemText = (TextView) viewItem.findViewById(R.id.item_text);

viewItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Triggers click upwards to the adapter on click
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(viewItem, position);
notifyItemChanged(selectedPos);
selectedPos =getAdapterPosition();
notifyItemChanged(selectedPos);
}
}
}
});
}
public void changeToSelect(int colorBackground) {
background.setBackgroundColor(colorBackground);
}
}

private List<String> list;
private Context context;

public TestAdapter(Context context, List<String> list) {
this.list = list;
this.context= context;
}

@Override
public TestAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View itemView = inflater.inflate(R.layout.test_cell_item, parent, false);
ViewHolder itemViewHolder = new ViewHolder(itemView);
return itemViewHolder;
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.changeToSelect(selectedPos == position ? Color.parseColor("#ca3854") : Color.BLACK);
TextView filterText = holder.itemText;
filterText.setTextSize(30);
filterText.setText(list.get(position));
}

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

Here you can see that i have created a Interface to use as the OnItemClickListener. I have defined a global variable to hold the currently selected item position. When everytime a view is clicked i change the selected item position and notifychanges to the adapter so that it can update its view with changes. OnBindViewHolder method i change the color of the background to select color if the position is currently selected position and to black if not.

In activity i used adapter like this,

        RecyclerView view = findViewById(R.id.view);
ArrayList<String> list = new ArrayList<>();
for(int i = 100; i < 150; i++) {
list.add(Integer.toString(i));
}
TestAdapter adaptor = new TestAdapter(this, list);
adaptor.setOnItemClickListener(new TestAdapter.OnItemClickListener() {
@Override
public void onItemClick(View viewItem, int position) {
//Your item click code
}
});
view.setAdapter(adaptor);
LinearLayoutManager liveImageLayoutManager = new LinearLayoutManager(getApplicationContext());
liveImageLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
view.setLayoutManager(liveImageLayoutManager);

I hope you can take a look at this and adapt how it is done to your code.

How to make single selection work in a nested RecyclerView

UPDATE: Managed to come up with a solution myself, although 100% sure, not the best approach.

First of all, implement Greenrobots EventBus:

implementation 'org.greenrobot:eventbus:3.1.1'

Now in the Activity where you hold both RecyclerViews register the Event listener:

 @Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}

and subscribe 2 methods. One for Parent Events and one for Children Events. This methods will trigger every time an item is selected!

    @Subscribe(threadMode = ThreadMode.MAIN)
public void onParentEventClicked(ParentAdapter.ParentEvent event) {
// to access the inner adapter here you must set it to public in the ParentAdapter(public ChildAdapter adapter;)
adapter.adapter.deSelectChild();
}

@Subscribe(threadMode = ThreadMode.MAIN)
public void onChildEventClicked(ChildAdapter.ChildEvent event) {
// normal ParentAdapter reference(ParentAdapter adapter;)
adapter.deSelectParent();
}

Inside your ParentAdapter create a method to deselect all parent items and a static class to fire the event:

public void deSelectParent()
{
for (int i=0;i<data.size();i++)
{
data.get(i).setSelected(false);
}
notifyDataSetChanged();
}

public static class ParentEvent {
View view;
int position;
}

Inside your ChildAdapter create a method to deselect all child items and a static class to fire the event:

public void deSelectChild()
{
for (int i=0;i<data.size();i++)
{
datachild.get(i).setSelected(false);
}
notifyDataSetChanged();
}

public static class ChildEvent {
View view;
int position;
}

now in both Parent and Child onBindViewHolders, you need similar logic for your models:

if (item.isSelected()) {
holder.yourbutton.setChecked(true);
} else {
holder.yourbutton.setChecked(false);
}

holder.yourbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ParentEvent event = new ParentEvent();
event.view = holder.yourbutton;
event.position = position;
EventBus.getDefault().post(event);
if (holder.yourbutton.isChecked()) {
for (int i = 0; i < data.size(); i++) {
data.get(i).setSelected(false);
}
data.get(position).setSelected(true);
} else {
data.get(position).setSelected(false);
}
notifyDataSetChanged();
}
});

And thats pretty much it, every click on a ParentItem will trigger the deselect method for ChildAdapter and vice-versa.
Due to the high usage of notifyDataSetChanged() I recommend using this line to get rid of the blinking:

 recycler_view_parent.setItemAnimator(null);

Any problems let me know!

How can I select only one checkbox in Recyclerview and notifydataset changed

this is the best code!
notice onBindViewHolder

public class SupportSchoolIdAdapter extends RecyclerView.Adapter<SupportSchoolIdAdapter.ViewHolder > {

private Context context;
ArrayList<SupportSchoolIdModel> supportSchoolIdModels;
private int selectedPosition = 0;
private ArrayList<Integer> selectCheck = new ArrayList<>();

public SupportSchoolIdAdapter (Context context, ArrayList<SupportSchoolIdModel> supportSchoolIdModels) {
this.context = context;
this.supportSchoolIdModels = supportSchoolIdModels;

//initilize selectCheck
for (int i = 0; i < supportSchoolIdModels.size(); i++) {
selectCheck.add(0);
}

}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.support_school_item, parent, false);
return new ViewHolder(v);
}

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

if (selectCheck.get(position) == 1) {
holder.checkbox.setChecked(true);
} else {
holder.checkbox.setChecked(false);
}

holder.checkbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int k=0; k<selectCheck.size(); k++) {
if(k==position) {
selectCheck.set(k,1);
} else {
selectCheck.set(k,0);
}
}
notifyDataSetChanged();

}
});
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

if(isChecked==true){
//Do whatever you want to do with selected value
}
}
});

}

@Override
public int getItemCount() {
return supportSchoolIdModels== null? 0: supportSchoolIdModels.size();
}

class ViewHolder extends RecyclerView.ViewHolde {

CheckBox checkbox;

public ViewHolder(View v) {
super(v);
checkbox = (CheckBox) v.findViewById(R.id.checkbox);
}

}

}

Single Selection item with Recycler Grid View

Here is the solution for your requirement

public class AdapterClass extends RecyclerView.Adapter<AdapterClass.ViewHolder> {
private int selected_position = -1;

@Override
public void onBindViewHolder(AdapterClass.ViewHolder holder, final int position) {
if (selected_position == position) {
// do your stuff here like
//Change selected item background color and Show sub item views

} else {
// do your stuff here like
//Change unselected item background color and Hide sub item views
}
// rest of the code here

holder.linelayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(selected_position==position){
selected_position=-1;
notifyDataSetChanged();
return;
}
selected_position = position;
notifyDataSetChanged();

}
});

//rest of the code here

}


}


Related Topics



Leave a reply



Submit