How to implement multi-select in RecyclerView?

空扰寡人 提交于 2019-11-26 03:07:50

问题


ListView had a multiple choice mode, what should I use for implementing the same using RecyclerView? How to handle onItemCheckedStateChanged? I checked this, But i couldn\'t make out much out of this. Any code snippet or a sample project implementing the same would be great. Thanks in advance.


回答1:


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 RectyclerView 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

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.




回答2:


Creation of those mentioned custom multi select implementation works correct but might have performance issues when the dataset is huge. I would highly recommend reading the section "Creating Recycle View - enable list-item selection" documentation by google. I have listed the link Android Documentation for creating recycle view an enable item click




回答3:


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


        private final Activity activity;
        private final ArrayList<ColorItem> itemArrayList;


        public RecyclerColorAdapter(Activity activity, ArrayList<ColorItem> itemArrayList) {
            super();
            this.activity = activity;
            this.itemArrayList = itemArrayList;
        }


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

        @Override
        public void onBindViewHolder(final ViewHolder holder, final int i) {
            holder.setIsRecyclable(true);

            final ColorItem colorItem = itemArrayList.get(i);


            holder.button_color.setText(colorItem.getColorName());

            holder.button_color.setBackgroundColor(colorItem.isSelected() ? Color.CYAN : Color.WHITE);

            holder.button_color.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    colorItem.setSelected(!colorItem.isSelected());
                    holder.button_color.setBackgroundColor(colorItem.isSelected() ? Color.CYAN : Color.WHITE);
                    if (colorItem.isSelected()){
                        arrayListColor.add("diamond_color[]="+colorItem.getValue()+"&");
                        Log.e("arrayListColor","---------"+arrayListColor);
                    }
                    else {
                        arrayListColor.remove("diamond_color[]="+colorItem.getValue()+"&");
                        Log.e("arrayListColor","---------"+arrayListColor);
                    }


                }
            });

        }

        @Override
        public int getItemCount() {

            return itemArrayList.size();
        }

        public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

            private Button button_color;

            public ViewHolder(View itemView) {
                super(itemView);
                itemView.setOnClickListener(this);
                button_color = (Button) itemView.findViewById(R.id.button_color);

            }

            @Override
            public void onClick(View v) {

            }

        }

    }



回答4:


Without creating model class we can multi select item in recyclerview. use this code in recyclerview adapter

holder.favplayIcon.setOnClickListener(View.OnClickListener {
                    if (!row_index.contains(position)) {
                        row_index.add(position)
                        holder.favplayIcon.setImageDrawable(
                            ResourcesCompat.getDrawable(resources, R.drawable.ic_starfilled, null ))

                    } else {
                        row_index.removeAt(row_index.indexOf(position))
                        holder.favplayIcon.setImageDrawable(
                   ResourcesCompat.getDrawable(resources,R.drawable.ic_starborder, null)
                        )  }
                })

///// put below code out of onclicklistener method of item
                if (!row_index.contains(position)) {

                    holder.favplayIcon.setImageDrawable(
                        ResourcesCompat.getDrawable(
                            resources,
                            R.drawable.ic_starborder,
                            null
                        )
                    )
} else {
                    holder.favplayIcon.setImageDrawable(
                        ResourcesCompat.getDrawable(
                            resources,
                            R.drawable.ic_starfilled,
                            null
                        )
                    )



回答5:


Simple and short way to do it:

  holder.parentLayout.setOnClickListener {

        if (holder.categoryIcon.isSelected) {
            selectedPos = position
        }

        if (selectedPos == position) {
            notifyItemChanged(selectedPos)
            selectedPos = RecyclerView.NO_POSITION
        } else {
            selectedPos = position
            notifyItemChanged(selectedPos)
        }
    }


    if (selectedPos == position) {
        holder.categoryIcon.setBackgroundColor(ContextCompat.getColor(context, R.color.orange))
        holder.categoryIcon.isSelected = true
    } else {
        holder.categoryIcon.setBackgroundColor(ContextCompat.getColor(context, R.color.white))
        holder.categoryIcon.isSelected = false
    }


来源:https://stackoverflow.com/questions/36369913/how-to-implement-multi-select-in-recyclerview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!