最近我在完成一个类似记事本的安卓应用程序,主界面显示所有笔记条目,用RecyclerView来完成整个笔记列表,就和大多数手机应用程序类似的列表,我想要让功能看上去更完整一些,因此萌生了为每一个条目增加一个侧滑菜单用于删除的想法,就像手机qq那样,实现的效果差不多就是这个样子:
通过侧滑RecyclerView中的item,使item显示出“隐藏”在侧边的菜单,菜单是一个图标,点击即可删除此条目。这个侧滑菜单实现的难度,对于一个安卓初学者来说难度也是够大了,初学者看什么都是全新的领域,多亏了强大的互联网,度娘帮我解决了这个世纪难题,提供了一条给初学者铺设的捷径,解决谜题的钥匙就是我们今天的主角——SwipeRecyclerView
SwipeRecyclerView是一个安卓开源第三方库,以作者本人的原话解释,该库基于RecyclerView的封装,提供了Item侧滑菜单、Item滑动删除、Item长按拖拽、添加HeaderView/FooterView、加载更多、Item点击监听等基本功能,该库除了以上新增加的功能以外,使用与安卓原生的RecyclerView完全一致,只是增加了这些新的特性方法。粗略介绍以后,我们来看看如何使用这个强大的SwipeRecyclerView来完成这个侧滑菜单
添加依赖:
在bulid.gradle中添加依赖
dependencies {
implementation 'com.yanzhenjie:recyclerview-swipe:1.1.4'
}
这只是我本人使用的版本而已,因为之前搜到的博客毕竟老,当时急于尝试这个强大的库所以没多想就直接用了博客里写的依赖,所以这个版本已经是一两年前的吧,但是SwipeRecyclerView库仍然在不断更新
更新的版本
如果使用的是android.support库在bulid.gradle上述位置中添加
implementation 'com.yanzhenjie.recyclerview:support:1.3.2'
如果使用的是androidx库在bulid.gradle上述位置中添加
implementation 'com.yanzhenjie.recyclerview:x:1.3.2'
SwipeRecyclerView从1.3.0版本开始支持AndroidX和二级列表,因此相对于低版本的包名和类名有所改动,从低版本升级的开发者需要考量是否要升级
为了让开发者方便切换support库和x库,SwipeRecyclerView的support库和x库除了依赖时的名称不一样外,包名、控件名和类名都是一样的,因此两个库不能共存
项目中使用:
将布局中的RecyclerView更换为SwipeRecyclerView
<com.yanzhenjie.recyclerview.swipe.SwipeRecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/note_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
com.yanzhenjie.recyclerview.swipe.SwipeRecyclerView>
Java中同样把原本RecyclerView出现的地方换成SwipeRecyclerView
private SwipeRecyclerView mNoteRecyclerView;
放下手中的原生RecyclerView吧
要实现侧滑菜单,光光定义一个SwipeRecyclerView肯定是不够的,我们还需要以下两个组件
private SwipeMenuItemClickListener itemMenuClickListener;
private SwipeMenuCreator menuCreator;
创建SwipeMenuItemClickListener
这是侧滑菜单的点击事件监听器,用来定义侧滑菜单的点击事件,看起来使用和一般的Button组件没有什么区别,都是在重载方法中写好点击事务逻辑,但是这里暗藏杀机,我就先卖个关子不说,因为我只有一个菜单项所以杀不了我。重载点击方法onItemClick(SwipeMenuBridge menuBridge)的参数SwipeMenuBridge menuBridge可以让我们获得当前开启侧滑菜单的条目究竟是哪一项,也就是定位需要被操作发生更改的条目了
itemMenuClickListener=new SwipeMenuItemClickListener() {
@Override
public void onItemClick(SwipeMenuBridge menuBridge) {
itemPosition=menuBridge.getAdapterPosition();//获取被开启侧滑菜单的item的位置
NoteLab noteLab= NoteLab.get(getActivity());
List<Note> notes=noteLab.getNotes();
Note note=notes.get(itemPosition);
if (note.isLiked()){
menuBridge.closeMenu();
Toast toast= Toast.makeText(getContext(),null, Toast.LENGTH_SHORT);
toast.setText("删除被收藏的记录是不对的!");
toast.show();
}else {
FragmentManager manager=getFragmentManager();
ConfirmDeleteFragment dialog=new ConfirmDeleteFragment();
dialog.setTargetFragment(NoteListFragment.this,REQUEST_DELETE_ITEM);
dialog.show(manager,DELETE);
}
}
创建SwipeMenuCreator
这是用来建立菜单的菜单构造器,在初始化该属性事需要在重载方法onCreateMenu(SwipeMenu swipeLeftMenu, SwipeMenu swipeRightMenu, int viewType)中构造自己需要的侧滑菜单,这个过程DIY的味道十足,仿佛是创造自己独一无二的侧滑菜单
menuCreator=new SwipeMenuCreator() {
@Override
public void onCreateMenu(SwipeMenu swipeLeftMenu, SwipeMenu swipeRightMenu, int viewType) {
int height= ViewGroup.LayoutParams.MATCH_PARENT;
SwipeMenuItem delete=new SwipeMenuItem(getActivity())
.setBackground(R.color.transparent)//菜单背景
.setImage(R.drawable.delete)//菜单图标
.setWidth(80)//菜单宽度
.setHeight(height);//菜单高度
swipeRightMenu.addMenuItem(delete);
}
};
新建一个菜单项的过程很明显是建造者模式,这里建造菜单项的过程非常自由,我们可以设置菜单的背景颜色,菜单的图标,菜单的宽度(单位是dp),菜单的高度(建议使用item的布局高度),以上虽然只展示了菜单项这四个属性,但构成菜单的元素可不止这些,这里我们可以用一个表格做一个集合
方法 | 作用 |
---|---|
setBackground(@DrawableRes int resId) 、setBackground(Drawable background) | 给菜单添加图片背景 |
setBackgroundColor(@ColorInt int color) | 给菜单项添加背景颜色 |
setImage(@DrawableRes int resId)、setImage(Drawable icon) | 给菜单项添加图标 |
setText(@StringRes int resId)、setText(String title) | 给菜单项添加文字 |
setTextColor(@ColorInt int titleColor) | 设置菜单项中文字的颜色 |
setTextSize(int titleSize) | 设置菜单项中文字的大小 |
setHeight(int height) | 设置菜单项的高度 |
setWeight(int weight) | 设置菜单项的宽度 |
当需要的菜单项都构造完毕后,就用swipeLeftMenu.addMenuItem(SwipeMenuItem item)或者是swipeRightMenu.addMenuItem(SwipeMenuItem item)方法将菜单项加入到侧滑菜单之中,swipeLeftMenu将菜单项加入到右滑出现的左侧菜单,swipeRightMenu将菜单项加入到左滑出现的右侧菜单,值得一提的是,方法addMenuItem可以反复多次使用,在一侧加入多个菜单项,这就看我们具体要实现什么功能了,但是这又引出了新的问题,还记得前文中提到的杀机吗?当单个条目两侧都添加了侧滑菜单,以及当一侧出现多个菜单项时,如何定位被点击的是哪一个菜单项?
举个例子,我一个笔记条目左右都设置了侧滑菜单,左边包含一个菜单功能是“收藏”,右边包含两个菜单,一个是“删除”,一个是“置顶”,那我在点击其中某个菜单项的时候,怎么在代码中确定哪个菜单项执行的是哪个功能呢?
定位被点击的是菜单中的哪一个菜单项
在我自己编写的项目里,侧滑菜单只出现了一个删除菜单项,在编写点击事件监听器时就省去定位菜单项这一步了,因为只有一个菜单项怎么点都必定是它,但是实际开发过程中面对的可能就不只这么简单了。
想要定位非常简单,第一步我们先在重载方法中获取菜单项位置
int direction = menuBridge.getDirection(); // 左侧还是右侧菜单
int menuPosition = menuBridge.getPosition(); // 菜单是单侧菜单中的哪一个菜单项
获取菜单项的位置以后,我们就可以利用判断语句来给不同的菜单项编写各自的功能
if (direction == SwipeRecyclerView.RIGHT_DIRECTION) {
//右侧菜单
if(menuPosition==1){
//定位到特定菜单项,编写点击事件
}else if(menuPosition==2){
}......
} else if (direction == SwipeRecyclerView.LEFT_DIRECTION) {
//左侧菜单
if(menuPosition==1){
//定位到特定菜单项,编写点击事件
}else if(menuPosition==2){
}......
}
完成了这一切以后,菜单的模样确定了,菜单点击了以后应该做什么也确定了,万事俱备,将这两个组件传递给SwipeRecyclerView就大功告成了
mNoteRecyclerView.setSwipeMenuCreator(menuCreator);
mNoteRecyclerView.setSwipeMenuItemClickListener(itemMenuClickListener);
到此关于使用SwipeRecyclerView实现侧滑菜单的方法就说完了,但是这只是SwipeRecyclerView所有功能的冰山一角罢了,开篇对SwipeRecyclerView的简单介绍中我们就能看到它的功能之多,想要了解更多我们可以查看作者在github的源码地址,这里有作者本人的使用说明,以及完成案例。下面我想展示部分作者以SwipeRecyclerView实现的一些平常看来炫酷的功能,也希望激起大家的学习兴趣,这个案例就在前面的源码地址里
SwipeRecyclerView的确是一个值得学习和使用的强大组件,我们能够通过它与其它组件灵活地结合使用,以相对来说十分简单的步骤,达到更加意想不到的效果。我觉得这个时代新生的菜鸟程序员们是十分幸运的,前人为我们做了很多,我们只要用好了工具就能完成漂亮的效果,SwipeRecyclerView也只是工具之一,而学习使用工具的过程是十分简单的,工具的制作才是对菜鸟来说遥不可及的事情。既然他们已经给我们的学习提供了巨大的便利,我们又有什么理由连轻松的事都不愿意认真做呢?看个编程博客也有毒鸡汤哈哈哈哈。但这些也是写给我自己看的,真的不能把学习的时间荒废了,站在巨人的肩膀上,我们应该要看得更远
作者:谢飞