如何解决如何在回收站视图android中选择多个项目?
我想在回收站视图中选择多个项目,当它被选中时,我想将可见性设置为该项目的复选框可见。因此,我能够使用接口设置 onlongClickListner
并在片段中处理 onLongClick
事件。
每当用户长按任何项目时,应用程序的 onCLick
逻辑就会改变。长按应用程序在另一个活动中打开该项目之前,但长按 onClick
后的逻辑已更改,可以根据需要进行设置。我想在长按后选中该项目对应的复选框。并希望从在回收站视图中加载的 arrayList
添加它。
片段
...
@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
处的复选框。在这种情况下,我无法实现代码。
我尝试过的事情
我确实尝试从 View v
传递 onLongClick(View v)
,然后将 selection
复选框传递给 onCLick()
事件。但是,它没有用。
我想从回收商视图中选择项目并将所选项目的可见性设置为 VISIBLE
。
------ 更新 ------
我现在可以借助事件方法中的少量编辑将复选框的可见性设置为可见。
片段
@Override
public void onclick(int position,CheckBox selection) {
if (!isSelectionMode) {
Intent intent = new Intent(getActivity(),arrayList.get(position).getUri());
startActivity(intent);
}
else
{
selection.setVisibility(View.VISIBLE);
selection.setChecked(true);
}
}
其中 selection
是从适配器的 MyViewHolder
类传递的复选框。但是,由于回收者视图的性质,我得到了双重选择。还有一个奇怪的问题,如果我向下滚动选择项目后,选择将随机更改。
在这张图片中,如您所见,我只选择了 4 张图片,但是当我向下滚动时,其他图片也被选中了,当我再次向上滚动时,它把我选择的项目弄乱了。
照片适配器
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,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 以这种方式工作,即回收视图。
因此,您必须隐藏、选中或取消选中每个视图膨胀的项目。
因此,在 onbindViewholder
中,您必须根据您的情况将 setChecked()
设为 true 或 false。
我解决这个问题的方法是: 不要将视图传递给父片段,而是以这种方式在适配器中保留检查逻辑:
if (isItemSelected){
selection.setChecked(true);
}else{
selection.setChecked(false);
}
这样做,就会有完美的检查和取消检查。
-- 更新 --
创建一个Selectable适配器类来提供isSelected()
方法如下
可选适配器
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
:
适配器类
public class RecyclerViewAdapter extends SelectableAdapter<RclAdapter.ViewHolder>
在片段上使用 toggleSelection
将位置设置为选中或未选中。
@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
。
在适配器中:onBindViewHolder
实现选择逻辑以显示和隐藏复选框。
如果只将其设置为View.VISIBLE
,而没有将未选中的设置为View.GONE
,您仍然会遇到同样的问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。