如何在回收站视图android中选择多个项目? [英] How to select multiple items in recycler view android?
问题描述
我想在回收站视图中选择多个项目,当它被选中时,我想将可见性设置为该项目的复选框可见.所以,很长时间我能够使用接口设置 onlongClickListner
并在片段中处理 onLongClick
事件.
I want to select multiple items in recycler view and when it is selected I want to set visibility as visible of a checkbox of that item. So, long I am able to set onlongClickListner
using interface and handling onLongClick
event in a fragment.
每当用户长按任何项目时,应用程序的 onCLick
逻辑就会改变.在长按应用程序在另一个活动中打开该项目之前,但是,长按 onClick
后的逻辑已更改,可以根据需要进行设置.我想在长按后选中该项目对应的复选框.并想从一个在回收器视图中加载的 arrayList
添加它.
Whenever user performes long click on any item, app's onCLick
logic is changed. Before long click app is opening the item in another activity but, after long click onClick
's logic is changed and can be set whatever I want. I want to check the checkbox corresponding to the item after long click. And want to add that from an arrayList
which is loaded in recycler view.
片段
...
@Override
public void onclick(int position) {
if (!isSelectionMode) {
Intent intent = new Intent(getActivity(), FullPhoto.class);
intent.putExtra("uri", arrayList.get(position).getUri());
startActivity(intent);
}
}
//Support fun to turn selectionMode on, onLongClick event.
@Override
public void onLongClick() {
isSelectionMode = true;
}
...
适配器
...
public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener {
private final ImageView img;
public CheckBox selection;
OnImageClickListner listner;
OnImageLongClickListener longClickListener;
public MyViewHolder(@NonNull View itemView, OnImageClickListner listner,OnImageLongClickListener longClickListener) {
super(itemView);
this.listner = listner;
this.longClickListener = longClickListener;
itemView.setOnLongClickListener(this); //onLongClickListener is set to all of the RecyclerView Items for once rather than setting on each item in BindViewHolder for repeated times
itemView.setOnClickListener(this); //onClickListener is set to all of the RecyclerView Items for once rather than setting on each item in BindViewHolder for repeated times
img = itemView.findViewById(R.id.img);
selection = itemView.findViewById(R.id.checkbox);
}
@Override
public void onClick(View v) {
listner.onclick(getAdapterPosition()); //Returning the current clicked position
}
@Override
public boolean onLongClick(View v) {
longClickListener.onLongClick();
return true;
}
}
// inner class ends
public interface OnImageClickListner{ //Interface to generate call back when user clicked an image.
void onclick(int position);
}
public interface OnImageLongClickListener{ //Interface to generate call back when user long clicked an image.
void onLongClick();
}
...
在这种情况下,我无法理解如何实现选择跟踪器.我可以使用 getAdapterPosition()
获取适配器位置,然后我可以从该索引上的 arrayList
中删除元素.但是,我想突出显示该 position
处的复选框.在这种情况下,我无法实现代码.
I this scenario, i am unable to understand how to implement a selection tracker. I can get the adapter position with getAdapterPosition()
and then I can remove the element from arrayList
on that index. But, I want to highlight the checkbox at that position
. In this case i am unable to implement the code.
我尝试过的事情
我确实尝试从 onLongClick(View v)
传递 View v
,然后将 selection
复选框传递给 onCLick()
事件.但是,它没有用.
I did try to pass the View v
from onLongClick(View v)
and then passing the selection
checkbox to onCLick()
event. But, It didn't work.
我想从回收站视图中选择项目并将所选项目的可见性设置为 VISIBLE
.
I want to select the items from recycler view and set visibility as VISIBLE
for the selected Items.
------ 更新 ------
------ Update ------
我现在可以借助事件方法中的少量编辑将复选框的可见性设置为可见.
I am now able to set visibility of the checkbox as visible with the help of few edits in event methods.
片段
@Override
public void onclick(int position, CheckBox selection) {
if (!isSelectionMode) {
Intent intent = new Intent(getActivity(), FullPhoto.class);
intent.putExtra("uri", arrayList.get(position).getUri());
startActivity(intent);
}
else
{
selection.setVisibility(View.VISIBLE);
selection.setChecked(true);
}
}
其中 selection
是从适配器的 MyViewHolder
类传递的复选框.但是,由于回收者视图的性质,我得到了双重选择.还有一个奇怪的问题,如果我向下滚动选择项目后,选择将随机更改.
Where selection
is a checkbox passed from MyViewHolder
class from adapter. But, because nature of the recycler view i am getting double selections. and one weird issues that after selecting items if I scroll down, selections will be changed randomly.
在这张图片中,如您所见,我只选择了 4 张图片,但是当我向下滚动时,其他图片也被选中了,当我再次向上滚动时,它把我选择的项目弄乱了.
In this image as you can see, I only selected 4 images but, when I scrolled down, other images were selected as well and when I scrolled up again it messed my selected items.
照片适配器
public class PhotosAdapter extends RecyclerView.Adapter<PhotosAdapter.MyViewHolder> {
public Context context;
ArrayList<ImageModel> arrayList;
Activity activity;
OnImageClickListner listener;
OnImageLongClickListener longClickListener;
/*=============================================================== CONSTRUCTOR ===============================================================*/
public PhotosAdapter(Context context, ArrayList<ImageModel> arrayList, Activity activity, OnImageClickListner listner, OnImageLongClickListener longClickListener) {
this.context = context;
this.arrayList = arrayList;
this.activity = activity;
this.listener = listner;
this.longClickListener = longClickListener;
}
/*=============================================================== OVERRIDDEN METHODS ===============================================================*/
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { //This methods returns single_view.xml as a view for RecyclerView.
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_view, parent, false);
return new MyViewHolder(view, listener, longClickListener);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { //Binding the uris with each view depending upon the position of current view.
activity.runOnUiThread(() -> GlideApp.with(context)
.load(Uri.parse(arrayList.get(position).getUri()))
.apply(RequestOptions.overrideOf(150, 150)) //It overrides the value of original image and reduces it to the visible thumbnail size.
.diskCacheStrategy(DiskCacheStrategy.RESOURCE) //Then it caches the reduced size thumbnail for faster loading speed.
.into(holder.img));
}
@Override
public int getItemCount() {
return arrayList.size();
}
/*=============================================================== INNER VIEW HOLDER CLASS ===============================================================*/
public static class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
private final ImageView img;
public CheckBox selection;
OnImageClickListner listener;
OnImageLongClickListener longClickListener;
public final SparseBooleanArray selectedItems; ///////////////////////////////// ADDED LINE /////////////////////////////////
public MyViewHolder(@NonNull View itemView, OnImageClickListner listener, OnImageLongClickListener longClickListener) {
super(itemView);
this.listener = listener;
this.longClickListener = longClickListener;
itemView.setOnLongClickListener(this); //onLongClickListener is set to all of the RecyclerView Items for once rather than setting on each item in BindViewHolder for repeated times
itemView.setOnClickListener(this); //onClickListener is set to all of the RecyclerView Items for once rather than setting on each item in BindViewHolder for repeated times
img = itemView.findViewById(R.id.img);
selection = itemView.findViewById(R.id.checkbox);
selectedItems = new SparseBooleanArray(); ///////////////////////////////// ADDED LINE /////////////////////////////////
}
@Override
public void onClick(View v) {
listener.onclick(getAdapterPosition(), selection); //Returning the current clicked position and selection checkbox to the implemented method.
}
@Override
public boolean onLongClick(View v) {
longClickListener.onLongClick(getAdapterPosition(), v); //Returning the current clicked position and view to the implemented method.
return true;
}
//////////////////////////////////////////////////////////////////////////// ADDED LINES ////////////////////////////////////////////////////////////////////////////
boolean isSelected(int position) {
return getSelectedItems().contains(position);
}
public void toggleSelection(int position) {
if (selectedItems.get(position, false)) {
selectedItems.delete(position);
} else {
selectedItems.put(position, true);
}
notifyItemChanged(position);
}
public void selectAll() {
for (int i = 0; i < getItemCount(); i++) {
if (!(selectedItems.get(i, false))) {
selectedItems.put(i, true);
}
notifyItemChanged(i);
}
notifyDataSetChanged();
}
public void clearSelection() {
List<Integer> selection = getSelectedItems();
selectedItems.clear();
for (Integer i : selection) {
notifyItemChanged(i);
}
}
public int getSelectedItemCount() {
return selectedItems.size();
}
public List<Integer> getSelectedItems() {
List<Integer> items = new ArrayList<>(selectedItems.size());
for (int i = 0; i < selectedItems.size(); ++i) {
items.add(selectedItems.keyAt(i));
}
return items;
}
} //INNER CLASS ENDS
/*=============================================================== INTERFACES ===============================================================*/
public interface OnImageClickListner { //Interface to generate call back when user clicked an image.
void onclick(int position, CheckBox selection);
}
public interface OnImageLongClickListener { //Interface to generate call back when user long clicked an image.
void onLongClick(int position, View v);
}
}
推荐答案
这就是导致双选或多选的原因.Recyclerview 以这种方式工作,即回收视图.
This is what is causing the double or multiple selections. Recyclerview works this way, that views are recycled.
因此,您必须隐藏、选中或取消选中每个视图膨胀的项目.因此,在 onbindViewholder
中,您必须根据您的情况将 setChecked()
设置为 true 或 false.
So you have to hide, check or uncheck each item everytine a view is inflated.
So in the onbindViewholder
you have to setChecked()
to true or false depending on your scenario.
我解决这个问题的方法是:不要将视图传递给父片段,而是以这种方式在适配器中保留检查逻辑:
My approach for this problem would be: Instead of passing views to the parent fragment, keep the check logic in the adapter this way:
if (isItemSelected){
selection.setChecked(true);
}else{
selection.setChecked(false);
}
这样做,就会有完美的检查和取消检查.
By so doing, there will be perfect checking and unchecking.
-- 更新 --
创建Selectable适配器类,提供isSelected()
方法如下
Create a Selectable adapter class to provide the isSelected()
method as follows
可选适配器
public abstract class SelectableAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
private static final String TAG = SelectableAdapter.class.getSimpleName();
private final SparseBooleanArray selectedItems;
SelectableAdapter() {
selectedItems = new SparseBooleanArray();
}
boolean isSelected(int position) {
return getSelectedItems().contains(position);
}
public void toggleSelection(int position) {
if (selectedItems.get(position, false)) {
selectedItems.delete(position);
} else {
selectedItems.put(position, true);
}
notifyItemChanged(position);
}
public void selectAll() {
for (int i = 0; i < getItemCount(); i++) {
if (!(selectedItems.get(i, false))) {
selectedItems.put(i, true);
}
notifyItemChanged(i);
}
notifyDataSetChanged();
}
public void clearSelection() {
List<Integer> selection = getSelectedItems();
selectedItems.clear();
for (Integer i : selection) {
notifyItemChanged(i);
}
}
public int getSelectedItemCount() {
return selectedItems.size();
}
public List<Integer> getSelectedItems() {
List<Integer> items = new ArrayList<>(selectedItems.size());
for (int i = 0; i < selectedItems.size(); ++i) {
items.add(selectedItems.keyAt(i));
}
return items;
}
}
让您的适配器扩展 selectableAdapter
如下:
Have your Adapter extend the selectableAdapter
as follows:
适配器类
public class RecyclerViewAdapter extends SelectableAdapter<RclAdapter.ViewHolder>
在片段上使用 toggleSelection
将位置设置为选中或未选中.
On the fragment use toggleSelection
to set a position as selected or not Selected.
@Override
public void onclick(int position) {
if (!isSelectionMode) {
Intent intent = new Intent(getActivity(), FullPhoto.class);
intent.putExtra("uri", arrayList.get(position).getUri());
startActivity(intent);
}
else
{
// Use the adapter instance here
adapter.toggleSelection(position);
}
}
记住 toggleSelection
通知适配器并调用 onBindViewHolder
.
Remember toggleSelection
notifies the adapter and calls onBindViewHolder
.
在适配器中:onBindViewHolder
实现选择逻辑以显示和隐藏复选框.如果你只将它设置为View.VISIBLE
,而不将它设置为View.GONE
,那么你仍然会遇到同样的问题.
In the adapter: onBindViewHolder
implement the selection logic to show and hide the checkbox.
If you only set it to View.VISIBLE
and don't set it to View.GONE
for the ones not selected, you will still have the same problem.
这篇关于如何在回收站视图android中选择多个项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!