当前位置:网站首页>RecyclerView的多选模式
RecyclerView的多选模式
2022-08-08 23:10:00 【jxq1994】
在ListView中实现多选并不困难,因为它是自带多选模式的,主要包括CHOICE_MODE_MULTIPLE
和CHOICE_MODE_MULTIPLE_MODAL
。如果你想要更深入的了解这两者是如何工作的。那么这篇文章是非常适合你的。
他们之间的区别大概就是CHOICE_MODE_MULTIPLE模式的特点在于他本身没有排斥性,在能选择item的情况下,也可以响应普通点击事件。
CHOICE_MODE_MULTIPLE_MODAL和CHOICE_MODE_MULTIPLE恰恰相反,他是对普通点击操作和多选操作是排斥的,一旦有一个item被选中,即进入到多选状态,item的onclick事件被屏蔽。这种排斥性也是他比CHOICE_MODE_MULTIPLE多了个MODAL的原因。
我们也可以利用这个多选模式完成RecyclerView的多选。
使用库实现选择模式
首先,导入库。将以下行添加到您的build.gradle:
compile 'com.bignerdranch.android:recyclerview-multiselect:+'
接下来,创建一个MultiSelector实例。在我的示例应用程序中,我在我的Fragment添加如下代码:
public class SDTxtListActivity extends AppCompatActivity {
RecyclerView recycler;
ArrayList<FileMsgModel> txtFiles;
private MultiSelector multiSelector = new MultiSelector();
...
}
MultiSelector是管理多选的核心对象。但是,您必须告诉MultiSelector何时进入/离开选择模式。
MultiSelector multiSelector = new MultiSelector();
multiSelector.setSelectable(true); // enter selection mode
MultiSelector multiSelector = new MultiSelector();
multiSelector.setSelectable(false); // leave selection mode
当选择某一项时,您还必须将ViewHolder告诉MultiSelector。
MultiSelector multiSelector = new MultiSelector();
multiSelector.setSelectable(true); // enter selection mode
multiSelector.setSelected(myViewHolder, true); // set myViewHolder to selected
SwappingHolder
您的ViewHolder必须实现SelectableHolder界面。该库提供了一个名为SwappingHolder的默认实现,用于处理被选择/未选择的视觉效果。
public class TxtFileHodler extends SwappingHolder implements View.OnClickListener,View.OnLongClickListener{
//(1)
private FileMsgModel dm;
private TextView textView;
public TxtFileHodler(View itemView) {
super(itemView,multiSelector); //(2)
textView = (TextView) itemView.findViewById(R.id.txtName);
itemView.setLongClickable(true);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
public void bindView(FileMsgModel fm){
this.dm = fm;
String txtName = dm.getFileName();
textView.setText(txtName);
}
@Override
public void onClick(View view) {
....
}
@Override
public boolean onLongClick(View view) { //(6)
if(!multiSelector.isSelectable()){ //(3)
multiSelector.setSelectable(true); //(4)
multiSelector.setSelected(TxtFileHodler.this,true); //(5)
return true;
}
return false;
}
}
创建一个子类SwappingHolder(1)的ViewHolder。当选择/取消选择时,MultiSelector可以通过SelectableHolder接口与ViewHolder进行通信。因此,您必须在ViewHolder的构造函数(2)中将MultiSelector传递给SwappingHolder。确保MultiSelector尚未处于选择模式(3),然后进入选择模式(4)。最后选择项目(5)。在这个例子中,我们选择长按(6)进入选择模式。您可以决定什么触发选择模式。
在选择模式下单击项目时,还可以通知MultiSelector。但是,您只需在选择模式下通知MultiSelector。当不在选择模式时,您可以正常处理项目点击。
该库提供了一种名为tapSelection()的方便方法。如果MultiSelector处于选择模式,则此方法将切换项目的选定状态并返回true。如果MultiSelector未处于选择模式,则此方法返回false。
public class TxtFileHodler extends SwappingHolder implements View.OnClickListener,View.OnLongClickListener{
private FileMsgModel dm;
private TextView textView;
public TxtFileHodler(View itemView) {
super(itemView,multiSelector);
textView = (TextView) itemView.findViewById(R.id.txtName);
itemView.setLongClickable(true);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
public void bindView(FileMsgModel fm){
this.dm = fm;
String txtName = dm.getFileName();
textView.setText(txtName);
}
@Override
public void onClick(View view) {
if(!multiSelector.tapSelection(TxtFileHodler.this)){
selectTxt(dm);
}
}
....
}
模拟多选模式
要获得CHOICE_MODE_MULTIPLE_MODAL同样的效果,您可以实现ActionMode.Callback。
但是,该库提供了一个名为ModalMultiSelectorCallback的抽象类。
private ModalMultiSelectorCallback mActionModeCallback
= new ModalMultiSelectorCallback(mMultiSelector) { // (1)
...
};
private class TxtFileHodler extends SwappingHolder implements View.OnClickListener, View.OnLongClickListener {
...
@Override
public boolean onLongClick(View view) {
if (!mMultiSelector.isSelectable()) {
((AppCompatActivity) getActivity()).startSupportActionMode(mActionModeCallback); // (2)
mMultiSelector.setSelectable(true);
mMultiSelector.setSelected(MyViewHolder.this, true);
return true;
}
return false;
}
}
首先创建一个ModalMultiSelectorCallback的实例,传入你的MultiSelector(1)。然后在启动ActionMode(2)时将此回调传递到系统中。
ModalMultiSelectorCallback公开ActionMode.Callback界面中通常用于创建/准备/响应/销毁ActionMode菜单项的所有方法:
public boolean onCreateActionMode(ActionMode mode, Menu menu);
public boolean onPrepareActionMode(ActionMode mode, Menu menu);
public boolean onActionItemClicked(ActionMode mode, MenuItem item);
public void onDestroyActionMode(ActionMode mode);
对于这个例子,我们使用想要在选择模式中这样做:
private ModalMultiSelectorCallback mActionModeCallback = new ModalMultiSelectorCallback(multiSelector) {
/** * actionmode的菜单处理 * 进入多选模式后,ActionBar/ToolBar上会弹出一个菜单,这个菜单需要我们自定义 * */
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = actionMode.getMenuInflater();
inflater.inflate(R.menu.sd_card_txt_menu,menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
//检查是否选中了某一项
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()){
case R.id.action_delete:
mode.finish();
List<FileMsgModel> files = new ArrayList<>();
for(int i = txtFiles.size()-1;i>=0;i--){
if(multiSelector.isSelected(i,0)){ // (1)
FileMsgModel fileModel = txtFiles.get(i);
files.add(fileModel);
}
}
Intent intent=new Intent();
intent.putExtra("MESSAGE", (Serializable) files);
setResult(2,intent);
finish();
multiSelector.clearSelections(); // (2)
return true;
default:
break;
}
return false;
}
/** * 关闭多选模式 */
@Override
public void onDestroyActionMode(ActionMode actionMode) {
new TxtFileAdapter(txtFiles).clearSelections();
}
};
private class TxtFileAdapter extends RecyclerView.Adapter<TxtFileHodler> {
private ArrayList<FileMsgModel> files;
public TxtFileAdapter(ArrayList<FileMsgModel> txtFiles) {
this.files = txtFiles;
}
@Override
public TxtFileHodler onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(SDTxtListActivity.this);
View view = inflater.inflate(R.layout.item,parent,false);
return new TxtFileHodler(view);
}
@Override
public void onBindViewHolder(TxtFileHodler holder, int position) {
FileMsgModel txt = files.get(position);
//我们可以用这行代码替换选中后的背景
holder.setSelectionModeBackgroundDrawable(getResources().getDrawable(R.drawable.sd_txt_back_drawable));
holder.bindView(txt);
}
@Override
public int getItemCount() {
return files.size();
}
//关闭Model
public void clearSelections() {
multiSelector.setSelectable(false);
notifyDataSetChanged();
}
}
我们可以访问每个选定的项目(1)并对其做处理。完成对所有项目的操作后,还需要清除选择(2)。
边栏推荐
猜你喜欢
2022杭电多校六 1007-Shinobu loves trip(同余方程)
(2022杭电多校六)1010-Planar graph(最小生成树)
(2022牛客多校四)N-Particle Arts(思维)
如何使用 Eolink 实现 API 文档自动生成
Kubernetes 实现 CI/CD 发布流程
Introduction to Qt (5) - file operation, hotkey and mouse reading (implementation of txt window)
用工具实现 Mock API 的整个流程
用模态框 实现 注册 登陆
PMP考点有哪些啊?
用工具实现 Mock API 的整个流程
随机推荐
如何使用 Eolink 实现 API 文档自动生成
You know you every day in the use of NAT?
Introduction to Qt (4) - Continuous playback of pictures (the use of two timers)
机器学习之知识点(一)
meta learning
如何搭建一套自己公司的知识共享平台
【Bug解决】ValueError: Object arrays cannot be loaded when allow_pickle=False
(2022杭电多校四)1001-Link with Bracket Sequence II(区间动态规划)
Low-Light Image Enhancement via a Deep Hybrid Network阅读札记
(2022杭电多校三)1011.Taxi(曼哈顿最值+二分)
CTFSHOW_WEB入门web213
JSDay2-两个数组的交集
2022牛客多校六 M-Z-Game on grid(动态规划)
【Pytorch】学习笔记(一)
JSDay2- 长度最小的子数组
JSDay1-合并两个有序数组
用工具实现 Mock API 的整个流程
stm32使用spi1在slave 模式下 dma 读取数据
Tp5 in cache cache, storage cell phone text message authentication code
WeChat applet develops some function usage methods