Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement multi-select in RecyclerView? [closed]

I'm trying to implement a RecyclerView with multiple selectable items.

Here is what I've tried but I couldn't make it work.

This is what I'm trying to do:

This is implemented using ListView

like image 859
Hegdekar Avatar asked Apr 02 '16 06:04

Hegdekar


People also ask

How to add multiple selection to android RecyclerView?

Multi Selection in Android RecyclerView For multi selection, we need to add one variable in our POJO (Employee. java) named isChecked as boolean. Now the logic is when user clicks any item of the recyclerview, we just set to true this field.

How many times onCreateViewHolder called?

By default it have 5.


1 Answers

I know it's a little bit late to answer this question. And I don't know whether it meets requirements of OP or not. But this may help someone. I implemented this multi-select RecyclerView with a simple trick. Here is my code.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:background="#EEE">     <android.support.v7.widget.RecyclerView        android:id="@+id/recycler_view"        android:layout_width="match_parent"        android:layout_height="match_parent" />  </RelativeLayout> 

item_row.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:layout_marginBottom="1dp"     android:background="#FFF"     android:clickable="true"      android:orientation="vertical">     <TextView       android:id="@+id/text_view"       android:layout_width="match_parent"       android:layout_height="wrap_content"       android:padding="10dp"       tools:text="TextView" />  </LinearLayout> 

In item_row.xml android:clickable="true" is important.

MainActivity.java

public class MainActivity extends AppCompatActivity {      private List<Model> mModelList;     private RecyclerView mRecyclerView;     private RecyclerView.Adapter mAdapter;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);         mAdapter = new RecyclerViewAdapter(getListData());         LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this);         mRecyclerView.setHasFixedSize(true);         mRecyclerView.setLayoutManager(manager);         mRecyclerView.setAdapter(mAdapter);     }      private List<Model> getListData() {       mModelList = new ArrayList<>();       for (int i = 1; i <= 25; i++) {           mModelList.add(new Model("TextView " + i));       }      return mModelList;     } } 

Model.java

public class Model {      private String text;     private boolean isSelected = false;      public Model(String text) {       this.text = text;     }      public String getText() {       return text;     }      public void setSelected(boolean selected) {       isSelected = selected;     }       public boolean isSelected() {       return isSelected;     } } 

RecyclerViewAdapter.java

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {      private List<Model> mModelList;      public RecyclerViewAdapter(List<Model> modelList) {       mModelList = modelList;     }      @Override     public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row, parent, false);        return new MyViewHolder(view);     }      @Override     public void onBindViewHolder(final MyViewHolder holder, int position) {         final Model model = mModelList.get(position);         holder.textView.setText(model.getText());         holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);         holder.textView.setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View view) {                 model.setSelected(!model.isSelected());                 holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);             }         });     }      @Override     public int getItemCount() {         return mModelList == null ? 0 : mModelList.size();     }      public class MyViewHolder extends RecyclerView.ViewHolder {          private View view;         private TextView textView;          private MyViewHolder(View itemView) {             super(itemView);             view = itemView;             textView = (TextView) itemView.findViewById(R.id.text_view);         }     } } 

How does it work? onBindViewHolder() method binds the data from ArrayList to View objects. So, on time binding the data to the view it gets the single object from ArrayList that is Model model = mModelList.get(position); with the current position. Now we need to check whether that particular object is selected or not. Like this,

model.isSelected() 

which returns either true or false. If that object is already selected we need to change the background color of row_item selected. For this here is the code

holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE); 

If it's selected change the background color to cyan else white.

For selection we need to use setOnClickListener() method. (here I am using only a TextView. So I am performing a click event on TextView). Here holder.view means the entire single item_row. Onclick toggle the boolean values to true or false.

 holder.textView.setOnClickListener(new View.OnClickListener() {         @Override         public void onClick(View view) {             model.setSelected(!model.isSelected());             holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);         }  }); 

In your Activity or Fragment which is hosting RecyclerView, you can get the selected objects/items like this

String text = "";  for (Model model : mModelList) {    if (model.isSelected()) {      text += model.getText();    }  } Log.d("TAG","Output : " + text); 

Here is the output

output

Edit 1: Restricting user to select only one item.

 private int lastSelectedPosition = -1;  // declare this variable  ...  // your code  ...     @Override public void onBindViewHolder(final MyViewHolder holder, int position) {     final Model model = mModelList.get(position);     holder.textView.setText(model.getText());     holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);     holder.textView.setOnClickListener(new View.OnClickListener() {         @Override         public void onClick(View view) {              // check whether you selected an item                          if(lastSelectedPosition > 0) {                 mModelList.get(lastSelectedPosition).setSelected(false);             }              model.setSelected(!model.isSelected());             holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);              // store last selected item position               lastSelectedPosition = holder.getAdapterPosition();           }     }); } 

I hope it will be helpful.

like image 82
Shashanth Avatar answered Oct 24 '22 14:10

Shashanth