Single and Multiple Item selection in RecyclerView Android

RecyclerView is major used in building any android app. So I have focused many featured of recyclerView in my last articles that we can implement. In this article I am focusing one common feature to used to single or multiple item selection in recyclerView.

There are many ways user can select items in recyclerView. I am giving some example that used almost times. Here are the details:

1. Single Selection Item (Radio Button).
2. Max limit items selection (Checkbox) .
3. Multiple Items selection.

Here is uploaded video with all three featured that what am talking with above three. Please check this video to understand before implement.



Thanks for watching this video. Lets create an android project to implements this feature.


build.gradle app level

    
  compile 'com.android.support:recyclerview-v7:25.0.0'
    compile 'com.android.support:cardview-v7:25.0.0'
    compile 'com.android.support:design:25.0.0'
    compile 'com.jakewharton:butterknife:8.4.0'
    apt 'com.jakewharton:butterknife-compiler:8.4.0'

ItemModel.java

    
public class ItemModel {

    private int id;
    private String name;
    private boolean isSelected;


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isSelected() {
        return isSelected;
    }

    public void setSelected(boolean selected) {
        isSelected = selected;
    }
}

MainActivity.java

    
 public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
    }

    @OnClick(R.id.single_selection)
    public void singleSelectionClicked(){

        Intent intent = new Intent(MainActivity.this, RecyclerViewActivity.class);
        intent.putExtra("TAG", "single");
        startActivity(intent);
    }

    @OnClick(R.id.max_selection)
    public void maxSelectionClicked(){
        Intent intent = new Intent(MainActivity.this, RecyclerViewActivity.class);
        intent.putExtra("TAG", "max");
        startActivity(intent);
    }

    @OnClick(R.id.multi_selection)
    public void multiSelectionClicked(){
        Intent intent = new Intent(MainActivity.this, RecyclerViewActivity.class);
        intent.putExtra("TAG", "multiple");
        startActivity(intent);
    }
}

RecyclerViewActivity.java

    
  import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.Toast;

import com.sunil.multiselectionrecyclerview.adapters.MultiMaxSelectionAdapter;
import com.sunil.multiselectionrecyclerview.adapters.MultiSelectionAdapter;
import com.sunil.multiselectionrecyclerview.adapters.SingleSelectionAdapter;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

/**
 * Created by sunil on 12/17/16.
 */

public class RecyclerViewActivity extends AppCompatActivity {

    @BindView(R.id.recyclerView)
    RecyclerView mRecyclerView;
    @BindView(R.id.selected)
    Button selected;

    private String tag;
    String names[] = Constant.name;

    SingleSelectionAdapter adapterSingle;
    MultiMaxSelectionAdapter adapterMultiMax;
    MultiSelectionAdapter adapterMulti;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recyclerview);
        ButterKnife.bind(this);

        initView();
    }

    private void initView() {

        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
            tag = bundle.getString("TAG");
        }

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);

        List list = getList();
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        if (tag.equalsIgnoreCase("Single")) {
            adapterSingle = new SingleSelectionAdapter(this, list);
            mRecyclerView.setAdapter(adapterSingle);
        } else if (tag.equalsIgnoreCase("max")) {
            adapterMultiMax = new MultiMaxSelectionAdapter(this, list);
            mRecyclerView.setAdapter(adapterMultiMax);
        } else if (tag.equalsIgnoreCase("multiple")) {
            adapterMulti = new MultiSelectionAdapter(this, list);
            mRecyclerView.setAdapter(adapterMulti);
        }
    }

    private List getList() {
        List list = new ArrayList<>();
        for (int i = 0; i < names.length; i++) {
            ItemModel model = new ItemModel();
            model.setName(names[i]);
            model.setId(i);
            list.add(model);
        }
        return list;
    }

    @OnClick(R.id.selected)
    public void selectedClick() {
        if (tag.equalsIgnoreCase("Single")) {
            if (adapterSingle.selectedPosition() != -1) {
                ItemModel itemModel = adapterSingle.getSelectedItem();
                String cityName = itemModel.getName();
                showToast("Selected City is: " + cityName);
            } else {
                showToast("Please select any city");
            }
        }else if (tag.equalsIgnoreCase("max")){
            List list = adapterMultiMax.getSelectedItem();
            if (list.size() > 0){
                StringBuilder sb = new StringBuilder();
                for (int index = 0; index < list.size(); index++){
                    ItemModel model = list.get(index);
                    sb.append(model.getName()+"\n");
                }
                showToast(sb.toString());
            }else{
                showToast("Please select any city");
            }
        }
        else if (tag.equalsIgnoreCase("multiple")){
            List list = adapterMulti.getSelectedItem();
            if (list.size() > 0){
                StringBuilder sb = new StringBuilder();
                for (int index = 0; index < list.size(); index++){
                    ItemModel model = list.get(index);
                    sb.append(model.getName()+"\n");
                }
                showToast(sb.toString());
            }else{
                showToast("Please select any city");
            }
        }
    }

    private void showToast(String message){
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

activity_recyclerview.xml

    
 <?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_marginBottom="50dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
   </android.support.v7.widget.RecyclerView>

   <Button
        android:id="@+id/selected"
        android:text="Selected Items"
        android:textColor="#fff"
        android:background="@color/colorPrimary"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

 </RelativeLayout>

SingleSelectionAdapter.java

    
  import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.TextView;

import com.sunil.multiselectionrecyclerview.ItemModel;
import com.sunil.multiselectionrecyclerview.R;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created by sunil on 12/17/16.
 */

public class SingleSelectionAdapter extends RecyclerView.Adapter {

    private List itemModels;
    private Context context;
    private int lastCheckedPosition = -1;

    public SingleSelectionAdapter(Context context, List itemModels) {
        this.itemModels = itemModels;
        this.context = context;
    }

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


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_single, viewGroup, false);
        return new ItemViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ItemModel model = itemModels.get(position);
        initializeViews(model, holder, position);
    }


    private void initializeViews(final ItemModel model, final RecyclerView.ViewHolder holder, int position) {
        ((ItemViewHolder)holder).name.setText(model.getName());
        if (model.getId() == lastCheckedPosition){
            ((ItemViewHolder)holder).radioButton.setChecked(true);
        }else{
            ((ItemViewHolder)holder).radioButton.setChecked(false);
        }
        ((ItemViewHolder)holder).radioButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                lastCheckedPosition = model.getId();
                notifyItemRangeChanged(0, itemModels.size());

            }
        });
    }

    public ItemModel getSelectedItem(){
        ItemModel model = itemModels.get(lastCheckedPosition);
        return model;
    }
    public int selectedPosition(){
       return lastCheckedPosition;
    }

    public static class ItemViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.name)
        TextView name;
        @BindView(R.id.radio)
        RadioButton radioButton;

        public ItemViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);

        }
    }
}

list_item_single.xml

    
 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_margin="5dp"
    android:layout_height="wrap_content">

    <android.support.v7.widget.CardView
        android:id="@+id/cardView"
        app:cardCornerRadius="0dp"
        app:cardUseCompatPadding="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:padding="15dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:padding="5dp"
                android:id="@+id/name"
                android:text="Name"
                android:textSize="16sp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <RadioButton
                android:padding="5dp"
                android:id="@+id/radio"
                android:layout_alignBaseline="@+id/name"
                android:layout_alignParentRight="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

        </RelativeLayout>

    </android.support.v7.widget.CardView>

</LinearLayout>

MultiMaxSelectionAdapter.java

    
  import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;

import com.sunil.multiselectionrecyclerview.ItemModel;
import com.sunil.multiselectionrecyclerview.R;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created by sunil on 12/17/16.
 */

public class MultiMaxSelectionAdapter extends RecyclerView.Adapter {

    private List itemModels;
    private Context context;
    int numberOfCheckboxesChecked = 0;

    public MultiMaxSelectionAdapter(Context context, List itemModels) {
        this.itemModels = itemModels;
        this.context = context;
    }

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


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_multi, viewGroup, false);
        return new ItemViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ItemModel model = itemModels.get(position);
        initializeViews(model, holder, position);
    }


    private void initializeViews(final ItemModel model, final RecyclerView.ViewHolder holder, int position) {
        ((ItemViewHolder)holder).name.setText(model.getName());
        ((ItemViewHolder)holder).checkBox.setChecked(model.isSelected());
        ((ItemViewHolder)holder).checkBox.setTag(new Integer(position));
        ((ItemViewHolder)holder).checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                CheckBox cb = (CheckBox)view;
                int clickedPos = ((Integer)cb.getTag()).intValue();
                if (cb.isChecked() && numberOfCheckboxesChecked >= 3){
                    cb.setChecked(false);
                    Toast.makeText(context, "Max allowed three checkbox only", Toast.LENGTH_LONG).show();
                }else {
                    if (cb.isChecked()) {
                        numberOfCheckboxesChecked++;
                    } else {
                        numberOfCheckboxesChecked--;
                    }
                    itemModels.get(clickedPos).setSelected(cb.isChecked());
                    notifyDataSetChanged();
                }
            }
        });
    }

    public  List getSelectedItem(){
        List itemModelList = new ArrayList<>();
        for (int i =0; i < itemModels.size(); i++){
           ItemModel itemModel = itemModels.get(i);
            if (itemModel.isSelected()){
                itemModelList.add(itemModel);
            }
        }
        return itemModelList;
    }

    public static class ItemViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.name)
        TextView name;
        @BindView(R.id.checkbox)
        CheckBox checkBox;

        public ItemViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);

        }
    }
}

list_item_multi.gradle

    
  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_margin="5dp"
    android:layout_height="wrap_content">

    <android.support.v7.widget.CardView
        android:id="@+id/cardView"
        app:cardCornerRadius="0dp"
        app:cardUseCompatPadding="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:padding="15dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:padding="5dp"
                android:id="@+id/name"
                android:text="Name"
                android:textSize="16sp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <CheckBox
                android:padding="5dp"
                android:id="@+id/checkbox"
                android:layout_alignBaseline="@+id/name"
                android:layout_alignParentRight="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

        </RelativeLayout>

    </android.support.v7.widget.CardView>

</LinearLayout>

MultiSelectionAdapter.java

    
  public class MultiSelectionAdapter extends RecyclerView.Adapter {

    private List itemModels;
    private Context context;

    public MultiSelectionAdapter(Context context, List itemModels) {
        this.itemModels = itemModels;
        this.context = context;
    }

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


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_multi, viewGroup, false);
        return new ItemViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ItemModel model = itemModels.get(position);
        initializeViews(model, holder, position);
    }


    private void initializeViews(final ItemModel model, final RecyclerView.ViewHolder holder, int position) {
        ((ItemViewHolder)holder).name.setText(model.getName());
        ((ItemViewHolder)holder).checkBox.setChecked(model.isSelected());
        ((ItemViewHolder)holder).checkBox.setTag(new Integer(position));
        ((ItemViewHolder)holder).checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                CheckBox cb = (CheckBox)view;
                int clickedPos = ((Integer)cb.getTag()).intValue();
                itemModels.get(clickedPos).setSelected(cb.isChecked());
                notifyDataSetChanged();
            }
        });
    }

    public  List getSelectedItem(){
        List itemModelList = new ArrayList<>();
        for (int i =0; i < itemModels.size(); i++){
            ItemModel itemModel = itemModels.get(i);
            if (itemModel.isSelected()){
                itemModelList.add(itemModel);
            }
        }
        return itemModelList;
    }

    public static class ItemViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.name)
        TextView name;
        @BindView(R.id.checkbox)
        CheckBox checkBox;

        public ItemViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);

        }
    }
}



Thanks for reading this post. I hope it will helps you.

1 comment:

Debug Database in Android

In my last tutorial, we have learned how we can use persistence database in android. We also understood which database wrapper we can use...

Contact Me

Name

Email *

Message *