RecyclerView的多选模式
来源:互联网 发布:球球刷爱心软件 编辑:程序博客网 时间:2024/05/29 18:16
在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 modemultiSelector.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)。
- RecyclerView的多选模式
- RecyclerView的观察者模式
- MVP模式的RecyclerView案例
- RecyclerView实现单选模式
- RecyclerView的MVP模式简单使用
- 从RecyclerView的源码了解观察者模式
- mvvm模式的recyclerview通用adapter
- MVP模式下的RecyclerView案例
- RecyclerView的单选和多选
- RecyclerView的多布局
- 多类型的RecyclerView
- RecyclerView的多条目展示
- 漂亮的Adapter模式-体会RecyclerView的设计实现
- Android RecyclerView 详解(五) RecyclerView多布局的使用
- RecyclerView 夜间模式
- 装饰设计模式--实现RecyclerView的addHeaderView()方法
- Android——RecyclerView下的观察者模式
- 一行代码实现RecyclerView的多选批量操作
- 定时器 — 换背景图片
- JS获取子节点、父节点和兄弟节点的若干种方式
- 关于信道的 编码,容量和带宽
- Poj 3304 Segments 【线段于直线相交】
- double类型输出,不以科学计数法方式输出
- RecyclerView的多选模式
- python爬取百度图片
- ActiveSupport eager_autoload源码分析
- MR练习之uid的去重
- 管理感言_进度把控2原则
- 简单的vim命令
- 高仿QQ空间广告位 ——— 一个位置来回切换两张广告图
- 2.0vue.js 第二种组件局部写法
- Performance Testing vs. Load Testing vs. Stress Testing