一步集成侧滑(删除)菜单,高仿QQ、IOS

来源:互联网 发布:万户网络官网 编辑:程序博客网 时间:2024/05/20 09:06

今日科技快讯

美图这家公司的产品相信大家都不会感到陌生,最开始推出的美图秀秀应用,因为简单易用、效果明显而瞬间圈得了不少忠实粉丝。后来推出的美拍、美颜相机和美图手机等都受到不少爱美人士的欢迎,目前美图旗下的应用已经在全球 11 亿个独立设备上激活,共计拥有 4.56 亿月活跃用户。用户众多的美图公司,终于在昨日(12 月 15 日) 早上 9 点 30 分时,成功在香港联合交易所主板正式挂牌交易。

作者简介

本篇来自老司机 张旭童 的投稿,动手能力很强的他,今天给大家带来侧滑菜单(删除按钮)开源库,希望大家喜欢。

张旭童 的博客地址:

https://gold.xitu.io/user/56de210b816dfa0052e66495

重要

重要的话开头说,not for the RecyclerView or ListView, for the Any ViewGroup.

本控件不依赖任何父布局,不是针对 RecyclerView、ListView,而是任意的ViewGroup里的childView都可以使用侧滑(删除)菜单。支持任意ViewGroup、0耦合、史上最简单。

概述

本控件从撸出来在项目使用至今已经过去7个月,距离第一次将它push至github上,也已经2月+。

之前,我发表过一篇文章。传送门:

http://gold.xitu.io/entry/57d1115dbf22ec005f9593c6/detail

里面详细描述了本控件V1.0版本是怎么实现的。

期间有很多朋友在评论、issue里提出了一些改进意见,例如支持设置滑动方向(左右)、高仿QQ的交互、支持GridLayoutManager等,以及一些bug。已经被我全部实、修复。并且将其打包至jitpack,引入更方便。和第一版相比,改动挺多的。故将其整理,新发一版。

那么本文先从如何使用它讲起,然后介绍它包含的特性、支持的属性。最后就几个难点和冲突的解决进行讲解。

代码传送门:喜欢的话,随手点个star。多谢

https://github.com/mcxtzhang/SwipeDelMenuLayout

先上几个gif给各位看官感受一下最新版的魅力(以下版本都顺便展示了可选的双向滑动)

本控件最大魅力就是0耦合,所以先上配合我另一个库组装的效果(ItemDecorationIndexBar + SwipeMenuLayout):

ItemDecorationIndexBar

https://github.com/mcxtzhang/ItemDecorationIndexBar

Android Special Version (无阻塞式,侧滑菜单展开时,依然可以展开其他侧滑菜单,同时上一个菜单会自动关闭):

GridLayoutManager (和上图的代码比,只需修改RecyclerView的LayoutManager。):

LinearLayout (不需任何修改,连LinearLayout也可以简单的实现侧滑菜单):

iOS interaction (阻塞式交互,高仿QQ,侧滑菜单展开式,屏蔽其他ITEM所有操作):

使用

Step 1. 在项目根build.gradle文件中增加JitPack仓库依赖。


Step 2. Add the dependency


Step 3. 在需要侧滑删除的ContentItem外面套上本控件,在本控件内依次排列ContentItem、菜单即可:

至此 您就可以使用高仿IOS、QQ 侧滑删除菜单功能了(侧滑菜单的点击事件等是通过设置的id取到,与其他控件一致,不再赘述)

Demo里,我的ContentItem是一个TextView,那么我就在其外嵌套本控件,并且以侧滑菜单出现的顺序,依次排列菜单控件即可。


支持属性

1. 通过 isIos 变量控制是否是IOS阻塞式交互,默认是打开的。

2. 通过 isSwipeEnable 变量控制是否开启右滑菜单,默认打开。(某些场景,复用item,没有编辑权限的用户不能右滑)

3. 通过开关 isLeftSwipe支持左滑右滑

有两种方式设置:

xml:


java代码:


支持特性
  • 不会同时展开2+个侧滑菜单。(可见界面上最多只会出现一个侧滑菜单)。

  • 侧滑过程中,禁止父控件上下滑动。

  • 多指同时滑动,屏蔽后触摸的几根手指。

  • 增加viewChache 的 get()方法,可以用在:当点击外部空白处时,关闭正在展开的侧滑菜单。

  • 以第一个子Item(即ContentItem)的宽度为控件宽度

每次更新的checklist

由于持续迭代,会发生完成一个feature、fix一个bug后,导致新的bug。

so,整理一份checkList,供每次迭代后验证,都通过,才会push到github库上。


难点、冲突的解决

1. ContentItem的长按和本控件侧滑的冲突

一开始我还是老思路,一直都是通过判断手指起始落点的坐标,判断手指落点处于何位置,屏蔽一些操作。当本控件功能越来越庞大,计算开始复杂,也容易出错。但也跌跌撞撞的撑了过来。

但就在今天,我想到了另一种思路:通过禁用子View的longClickable属性来完成这个功能。于是我重构这部分代码,先利用git 查看之前的提交,去除掉那部分代码,并在侧滑菜单展开smoothExpand()、关闭smoothClose()的函数中分别加入:


代码就这么简单,几小时前我才想到这么简单的解决方法,这也是促使我新撸一遍文章,记录本控件的一些改动的缘由之一。

2. 如何支持任意父控件

这算是本控件最酷炫的魅力之一吧,在之前的文章 ,我详细描述了实现过程。

总结起来,我利用了一个static变量,保存了当前正在展开的View,在进行各项操作时就可预先判断,如若会引起冲突,例如界面上出现两个侧滑菜单,便自动关闭上一个菜单。

代码如下:

//存储的是当前正在展开的View
private static SwipeMenuLayout mViewCache;

dispatchTouchEvent() 的ActionDown里:


在侧滑菜单展开 smoothExpand()、关闭 smoothClose() 的函数:

//展开就加入ViewCache:
mViewCache = SwipeMenuLayout.this;
//关闭置为null
mViewCache = null;

onDetachedFromWindow() 里:


3. 解决多指滑动冲突

利用一个布尔值 flag,在ActionDown时判断是否继续接受触摸事件:

代码如下:

//防止多只手指一起滑,我的flag在每次down里判断,touch事件结束清空
private static boolean isTouching;

dispatchTouchEvent() 的ActionDown里:


ActionUp里:

//没有手指在摸我了
isTouching = false;

4. 支持GridLayoutManager

毕竟项目中在网格布局中使用侧滑菜单还属少数,所以一开始我将场景简单化,给本控件设置的宽度都是父控件的宽度-padding。后来有童鞋提出希望支持网格布局,一开始我思路也走了弯路,我还想着构建一个MatchParent的MeasureSpec,然后传给父控件(GridView、RecyclerView)用于测量呢。

正确思路是,取第一个子View,即ContentView的宽度用作本控件的宽度即可,这样在layout侧滑菜单时,自然而然将侧滑菜单layout在了不可见的区域,只有通过滑动才能显示它。代码也没啥好说的:

在onMeasure()中:


在onLayout()中,顺序layoutchildView即可。

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

原创粉丝点击