前言

SmartSwipe是一个Android侧滑处理框架,它封装了对控件侧滑事件(上/下/左/右4个方向滑动的手势事件)的捕获、分发及多点交替滑动的处理,基于SmartSwipe我们可以为控件添加各种你想要的侧滑效果。

先来看看它能做些什么吧!

如果已经了解SmartSwipe的功能,只是想了解他的实现原理

可跳过第一节,直接看第二节的原理介绍。

如果觉得文章还不错,欢迎小伙伴们关注,您的关注就是我最大的动力!我会定期分享Android知识点及解析,还会不断更新的BATJ面试专题,欢迎大家前来探讨交流,如有好的文章也欢迎投稿。

一、 用法及演示

1.1 一行代码实现全局侧滑返回

//仿手机QQ的手势滑动返回SmartSwipeBack.activityStayBack(application, null); //仿微信带联动效果的透明侧滑返回SmartSwipeBack.activitySlidingBack(application, null); //侧滑开门样式关闭activitySmartSwipeBack.activityDoorBack(application, null); //侧滑百叶窗样式关闭activitySmartSwipeBack.activityShuttersBack(application, null); //仿小米MIUI系统的贝塞尔曲线返回效果SmartSwipeBack.activityBezierBack(application, null);

效果图:

1.2 一行代码让页面动起来

//为控件添加仿iOS的弹性留白效果://当纵向不能滚动(或滚动到顶/底)时,若继续拖动,则UI呈现弹性留白效果,释放后平滑恢复SmartSwipe.wrap(view) .addConsumer(new SpaceConsumer()) .enableVertical();

效果图:

1.3 一行代码让页面具有弹性

//为控件添加仿MIUI的弹性拉伸效果://当纵向不能滚动(或滚动到顶/底)时,若继续拖动,则UI呈现弹性拉伸效果,释放后平滑恢复SmartSwipe.wrap(view) .addConsumer(new StretchConsumer()) .enableVertical();

效果图:

1.4 一行代添加下拉刷新

//xxxMode第二个参数为false,表示工作方向为纵向:下拉刷新&上拉加载更多//如果第二个参数设置为true,则表示工作方向为横向:右拉刷新&左拉加载更多SmartSwipeRefresh.drawerMode(view, false).setDataLoader(loader);SmartSwipeRefresh.behindMode(view, false).setDataLoader(loader);SmartSwipeRefresh.scaleMode(view, false).setDataLoader(loader);SmartSwipeRefresh.translateMode(view, false).setDataLoader(loader);

样式 drawerMode

效果图

样式 behindMode

效果图

样式 scaleMode

效果图

样式 translateMode

效果图

1.5 一行代码添加滑动菜单

SmartSwipe.wrap(view) //添加抽屉效果,其效果与DrawerLayout相似 // DrawerLayout只支持左右2个方向,而DrawerConsumer支持上下左右4个方向 .addConsumer(new DrawerConsumer())  //设置横向(左右两侧)的抽屉为同一个view(常见的侧滑显示删除按钮的功能) .setHorizontalDrawerView(buttonsViewGroup)  .setScrimColor(0x2F000000) //设置遮罩的颜色 .setShadowColor(0x80000000) //设置边缘的阴影颜色 ;

效果图:

1.6 一行代码添加具有联动效果的滑动菜单

SmartSwipe.wrap(view) .addConsumer(new SlidingConsumer()) .setRelativeMoveFactor(0.3F) //联动系数 .setHorizontalDrawerView(buttonsView) .setScrimColor(0x2F000000) ;

效果图:

1.7 炫酷的封面

SmartSwipe.wrap(coverView) .addConsumer(new ShuttersConsumer()) //百叶窗效果 .setScrimColor(0xAF000000) .enableAllDirections() .addListener(new SimpleSwipeListener() { @Override public void onSwipeOpened(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) { //封面打开后自动隐藏或移除 wrapper.setVisibility(View.GONE); } });

效果图:

SmartSwipe.wrap(coverView) .addConsumer(new DoorConsumer()) //开门效果 .setScrimColor(0xAF000000) .enableAllDirections() .addListener(new SimpleSwipeListener() { @Override public void onSwipeOpened(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) { //封面打开后自动隐藏或移除 wrapper.setVisibility(View.GONE); } });

效果图:

二、实现原理

2.1 先介绍一下ViewDragHelper

ViewDragHelper是Android官方支持库中有一个工具类。它可以帮助我们处理控件的拖拽:先创建一个自定义ViewGroup,将被拖动的控件添加到这个自定义ViewGroup中,并用ViewDragHelper来处理控件的拖拽。

ViewDragHelper的主要作用是:拦截父容器的touch事件,捕获一个子控件来进行拖拽,通过改变这个子控件的left和top来将其在父容器中重新定位,从而达到拖拽的效果。

在官方支持库中,滑动抽屉相关的SlidingPaneLayout和DrawerLayout,以及CoordinatorLayout布局相关的BottomSheetBehavior和SwipeDismissBehavior,都能看到ViewDragHelper的身影。

但是,ViewDragHelper的名称也表明它就是用来处理拖拽的,拖拽的对象必须是一个子View,在拖拽的过程中需要改变子控件的left和top,对于一些没有子View被拖拽的侧滑效果(例如:MIUI系统的贝塞尔曲线侧滑返回效果、手机QQ的侧滑返回效果及MIUI官方app中的普遍使用了的弹性拉伸效果等等),却有点力有不逮。

2.2 借鉴ViewDragHelper实现侧滑处理

针对侧滑这个手势,我们能不能将它的概念抽象一下,到底侧滑指的是什么呢?

  • 狭义侧滑:从屏幕的某个边缘开始向着远离该边缘的方向滑动
  • 广义侧滑:手指在屏幕上按下之后向着某个方向滑动

我的理解是,广义侧滑包含狭义侧滑,只不过是触发区域是否在屏幕边缘的区别罢了。

既然侧滑手势能被明确地抽象出来,那么我们是否可以借鉴ViewDragHelper的事件拦截思路将它做这样的封装?

对被侧滑控件的touch事件进行拦截分析,确认是否将其捕获作为侧滑手势然后计算好侧滑的实时位移(手指滑动的位移,而不是不依赖于View的left与top)再通过策略模式(Strategy Pattern)使用不同的策略不断消费侧滑的位移来进行侧滑效果的UI呈现。

答案是肯定的!

2.3 SmartSwipe的实现原理

SmartSwipe在ViewDragHelper的基础上,将它对子View的捕获及移动处理改造成对父View自身触摸事件的定性(能否及是否捕获)、定向(捕获的事件所触发的侧滑方向)及定位(事件捕获之后在侧滑方向上移动的距离),并将侧滑距离交由SwipeConsumer来消费,SwipeConsumer根据侧滑距离的变化对控件布局进行相应的改变。

SmartSwipe的封装思路如下:

  • 用一个ViewGroup将需要处理侧滑事件的控件View包裹起来(被包裹起来的控件作为它的contentView)
  • 可以为这个ViewGroup添加一些附属控件(如:滑动抽屉)
  • 拦截这个ViewGroup的touch事件,并将touch事件转换为侧滑距离交给SwipeConsumer进行消费
  • SwipeConsumer根据侧滑距离的变化对控件布局进行相应的改变
  • 通过继承SwipeConsumer,用不同的方式来改变控件布局(例如:对contentView及附属控件的位置、缩放、透明等进行改变),从而实现各种侧滑的效果。

于是,侧滑的手势事件识别及滑动距离计算的工作在框架内部就统一完成了,至于根据侧滑距离来实现各种不同的UI呈现效果,就可以很方便地通过继承SwipeConsumer来实现了。

2.4 如何创建自定义SwipeConsumer?

以框架内置的仿MIUI系统应用中弹性拉伸效果的实现为例

根据侧滑距离,对contentView进行缩放和平移,从而实现弹性拉伸效果

代码如下:

public class StretchConsumer extends SwipeConsumer { @Override public void onDetachFromWrapper() { super.onDetachFromWrapper(); View contentView = mWrapper.getContentView(); if (contentView != null) { contentView.setScaleX(1); contentView.setScaleY(1); contentView.setTranslationX(0); contentView.setTranslationY(0); } } @Override public void onDisplayDistanceChanged(int distanceXToDisplay, int distanceYToDisplay, int dx, int dy) { View contentView = mWrapper.getContentView(); if (contentView != null) { if (distanceXToDisplay >= 0 && isLeftEnable() || distanceXToDisplay <= 0 && isRightEnable()) { contentView.setScaleX(1 + Math.abs((float) distanceXToDisplay) / mWidth); contentView.setTranslationX(distanceXToDisplay / 2F); } if (distanceYToDisplay >= 0 && isTopEnable() || distanceYToDisplay <= 0 && isBottomEnable()) { contentView.setScaleY(1 + Math.abs((float) distanceYToDisplay) / mHeight); contentView.setTranslationY(distanceYToDisplay / 2F); } } }}

以上就是实现弹性拉伸效果的全部代码,很简单,不是吗?

它的使用方式同样简单:

SmartSwipe.wrap(view) //指定目标控件 .addConsumer(new StretchConsumer()) //添加弹性拉伸效果 .enableVertical(); //指定工作方向为:上、下2个方向

再来看看仿手机QQ侧滑返回的效果如何实现

手机QQ侧滑时UI没有任何变化在手指释放时,根据滑动的方向和速率来决定是否finish当前Activity

代码如下:

public class StayConsumer extends SwipeConsumer { private int mMinVelocity = 1000; public StayConsumer() { //不能通过滑动距离判断是否需要打开 setOpenDistance(Integer.MAX_VALUE) .setMaxSettleDuration(0); //打开时无需动画,时间置为0 } @Override protected void onDisplayDistanceChanged(int distanceXToDisplay, int distanceYToDisplay, int dx, int dy) { //滑动时不需要对contentView做任何改变 } @Override public void onSwipeReleased(float xVelocity, float yVelocity) { //在释放时,根据速率和方向来决定是否打开 if (Math.abs(xVelocity) > Math.abs(yVelocity)) { if (mDirection == DIRECTION_LEFT && xVelocity >= mMinVelocity || (mDirection == DIRECTION_RIGHT && xVelocity <= -mMinVelocity)) { //置为打开状态 mCurSwipeDistanceX = getSwipeOpenDistance(); mProgress = 1; } } else { if (mDirection == DIRECTION_TOP && yVelocity >= mMinVelocity || (mDirection == DIRECTION_BOTTOM && yVelocity <= -mMinVelocity)) { //置为打开状态 mCurSwipeDistanceY = getSwipeOpenDistance(); mProgress = 1; } } super.onSwipeReleased(xVelocity, yVelocity); } public int getMinVelocity() { return mMinVelocity; } //支持使用者设置最低速率的阈值 public StayConsumer setMinVelocity(int minVelocity) { if (minVelocity > 0) { this.mMinVelocity = minVelocity; } return this; }}

是不是也很简单!

最后

码字不易,如果觉得文章还不错的朋友点赞+关注+转发,我会定期分享Android知识点及解析,还会不断更新的BATJ面试专题以及互联网趣事,欢迎大家前来探讨交流,如有好的文章也欢迎投稿。

oppo 手机侧滑快捷菜单_你见过微信侧滑返回的联动效果,但开门效果、百叶窗效果见过吗?...相关推荐

  1. oppo 手机侧滑快捷菜单_关于oppo手机菜单键调出的方法,原来是这样的

    用OPPO手机朋友们,今天来教大家如何调出手机菜单键. 工具/材料 OPPO手机 操作方法 01 首先,在手机桌面上找到设置,点击进入. 02 进入设置找到[面部与密码],并点击它. 03 然后点击[ ...

  2. oppo 手机侧滑快捷菜单_为什么华为OV都要推出瀑布屏手机?瀑布屏优势劣势大盘点...

    2018年手机配色被友商们玩出了各种新花样,从无数渐变色到稀奇古怪蚀刻工艺,再到天空之镜一锤落音,可以说在配色方面已经被所有厂家"玩坏",以至于再也不能代表手机设计语言创新的分毫. ...

  3. oppo 手机侧滑快捷菜单_预算5-6K哪款国产手机更香?华为、OPPO、小米这几款新机618卖爆...

    近期,很多小伙伴因为618的到来,都想要在这个优惠福利多多的时间段中换购一款5G手机.那当下5G手机琳琅满目,哪款才是最值得挑选或入手的呢?从众多品牌推出的5G新品来看,旗舰手机是最值得入手的,毕竟拥 ...

  4. oppo 手机侧滑快捷菜单_[图]OPPO又出脑洞设计:弹出/侧滑第二块手机屏幕

    在推进全面屏提升屏占比的主流趋势下,目前市场上主要划分为三派,以苹果为代表的"刘海".以三星为代表的"打孔"以及OPPO.vivo等国内手机厂商所代表的&quo ...

  5. oppo 手机侧滑快捷菜单_是王者回归还是昙花一现,侧滑全键盘手机,你会选择吗...

    时间飞快,转眼2019年过去半年,再过三个月又是世界手机三大巨头相继发布年度旗舰手机产品的时候了.不过在他们发布前,也就下个月即将上市一部不引人注意的怀旧型手机,我们都知道,现在手机的发展的潮流是往全 ...

  6. oppo 手机侧滑快捷菜单_各种手机查看APP使用时间的方法

    很多朋友想要戒手机,却不知哪个APP里可以查看,其实每一种手机 都有自己查看APP使用时间的方法. 一 华为手机 找到负一层,(负一层指的是主页面左边那个页面),找到几个功能的快捷方式,找到左下方情境 ...

  7. oppo 手机侧滑快捷菜单_oppo手机隐藏的实用功能,关键时刻帮大忙!

    OPPO手机是我国非常热销的一个手机品牌,身边有不少的小伙伴都在用OPPO的手机.那么,OPPO手机上一些实用的小功能,你们都了解吗?我想大部分人对这些都不是很了解,下面我们就一起来看看OPPO上有哪 ...

  8. oppo 手机侧滑快捷菜单_OPPO手机的十年之路,创新精神让品牌再升华

    从2008年进入手机行业算起,OPPO做手机已经整整十年了.从2008年到2018年,OPPO手机业务从零起步,秉持日行一步的精神和努力,取得令人瞩目的成绩.随着国内智能手机市场竞争白热化和国产手机发 ...

  9. oppo 手机侧滑快捷菜单_OPPO十年进化论,从A·V厂到国内第二

    昨天OPPO召开了技术沟通会,正式发布了之前预热已久的最新相机技术,10倍混合光学变焦技术.之所以叫混合,正是因为采用了超广角.超清主摄和长焦三种镜头,能实现15.9-159mm等效焦段,而一般的镜头 ...

最新文章

  1. php 爬虫_Rad爬虫结合W13Scan扫描器挖掘漏洞
  2. 注册表----修改Win7登录界面
  3. Python3学习笔记(二):基本数据类型
  4. 浅谈 Nginx与PHP 交互
  5. Cortex-M3 内部寄存器
  6. 2022年为什么要使用Flutter构建应用程序?
  7. fms3 NetConnection.Connect.Rejected 问题
  8. Windows上安装Mysql解压缩版教程
  9. SAP Fiori里Contact Support的按钮渲染逻辑
  10. css 宋体_Java前端基础(一)之html/css
  11. sml完整形式_411的完整形式是什么?
  12. prop attr 到底哪里不一样?
  13. centos系统安装python3.8的操作过程 亲测可行 云服务器安装过程 200327
  14. C++使用using与typedef定义别名
  15. 原码一位乘法和补码一位乘法
  16. One Click软件简介
  17. sqlite数据库的版本更替
  18. AI智能视频分析系统提升水泥厂安全监管解决方案
  19. 妹子图kotlin版
  20. YOLO UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing a

热门文章

  1. Js 常用的格式验证(手机号、邮箱,身份证)
  2. linux查看mysql版本_Linux系统中查看MySQL版本的五种方法
  3. 一起学习正则表达式(四)常见的4种匹配模式
  4. Python3 selenium获取起点收藏榜单Top100并解析字体加密
  5. 微信小程序开发学习--7.27日
  6. 自制QQ 数据库SQL语句 代码
  7. AutoGPT自主人工智能用法和使用案例
  8. 程序员,请昂起你高贵的头!
  9. 【招行】信用卡推荐用户列表 数据岗
  10. mysql数据库客户端_5款好用的mysql客户端