轻松实现微信滑动返回页面效果
1.项目概要:
2.背景和需求
主流的 APP 的页面结构,顶部有一个 ActionBar 或者 Toolbar 的标题栏,下边是我们的页面自定义内容。标题栏里面由 2 部分组成,一个是返回按钮,另一个是标题。通过监听返回按钮的点击事件,即可返回上一个页面,实现页面切换和用户交互。典型 APP 标题栏结构如下图所示。
主流 APP 的页面返回方式对比:
APP 类型:常规应用、Google 官方应用、IDE 新建 Demo
返回方式:1.点击返回按钮 2.系统导航栏返回按钮
实现原理:1.监听 Button 的 OnClickListener,在调用 Activity.finish()或 Activity.onBackPress()
特点:点击即可自动返回,这个动作只会产生一个效果
APP 类型:微信
返回方式:1.点击标题栏返回按钮 2.系统导航栏返回按钮 3.从页面左边沿开始向右活动返回
实现原理:1.前 2 种方法同上 2.第 3 种方法,是本文研究的重点
特点:除了同上特点,还支持动画、拖拽,可能停留在当前页面,或者返回上一页面,增加了互动效果和用户粘性
APP 类型:美团
返回方式:1.点击标题栏返回按钮 2.系统导航栏返回按钮
实现原理:同第一种应用
特点:点击即可自动返回,这个动作只会产生一个效果
需求:如何轻松实现微信滑动返回页面效果?
3.实现原理
3.1 定义:
用户的手指触摸屏幕,从左边沿往右滑动;当手指在屏幕上移动时,当前页面会跟随手指移动;当手指离开屏幕时,会根据松手时的滑动速度、和松手的位置 2 个条件来决定是停留在当前页面还是返回上一页面。细心的读者可实际观察下交互效果。
3.2 需求分析:
对用户的手指触摸进行跟踪:View.onTouchEvent,View.onInterceptTouchEvent
对页面进行移动:View.scrollTo/View.scrollBy,OverScroller,Animation
停留在当前页面:把页面移动的距离反向移动即可
返回上一层页面:把当前页面回收即可
总结:根据上面的分析,这个功能本质上是关于触摸反馈、滑动、动画等知识点的综合应用,一种方法是利用 View.onTouchEvent+View.scrollTo/View.scrollBy 来实现;另一种方法,Android 系统其实给我们提供了对 View 进行拖拽的 API,如:ViewDragHelper、OnDragListener。
3.3 ViewDragHelper 的使用方法:
定义:ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number of useful operations and state tracking for allowing a user to drag and reposition views within their parent ViewGroup. 是一个用于开发通用 ViewGroup 工具类,提供了许多用户在 ViewGroup 内部拖拽和移动子 View 的方法和状态跟踪的方法。
需要创建⼀个 ViewDragHelper 和 ViewDragHelper.Callback()
需要写在 ViewGroup 里面,重写 onInterceptTouchEvent() 和 onTouchEvent()
例子:
3.4 OnDragListener 的使用方法:
定义:Interface definition for a callback to be invoked when a drag is being dispatched to this view. The callback will be invoked before the hosting view's own onDrag(event) method. 当 View 收到一个拖拽事件时,这个监听器的接口就会被调用;且先于被拖拽的子 View 的父控件的 onDrag(event)调用。
通过 startDragAndDrop() 来启动拖拽
用 View.setOnDragListener() 来监听:OnDragListener 内部只有一个方法:onDrag(event),ViewGroup.onDragEvent() 方法也会收到拖拽回调
例子:
3.5 对比总结:
ViewDragHelper(support v4):
应用场景:用户拖动 ViewGroup 中的某个子 View
特点:需要拦截复空间的触摸事件,拖拽的对象是子 View 本身,关注的是子 View 的位置移动
原理:实时修改被拖拽的子 View 的 位置参数(如:left, top 值)
OnDragListener(API 11):
应用场景:用户的 拖起 -> 放下 操作,侧重点在于内容的移动,可以附加拖拽数据
特点:是 View 自带的一个监听器,不需要父控件参与。关注的是事件,无法移动 View 的位置,拖动的只是一个 View 拷贝,支持跨进程传递数据
原理:创造出⼀个图像在屏幕的最上层,图像跟随用户手指移动
4.使用方法
有了前文的铺垫,我们开始实现微信滑动返回页面效果,因为需要对页面进行滑动,本质上是对 View 的移动,所以选择 ViewDragHelper 来实现。
4.1 新建 BeSmartViewDragHelperCallback:
4.2 新建 ViewDragHelper:
4.3 重写父控件的 onInterceptTouchEvent 和 onTouchEvent:
4.4 封装 SmartReturnHelper 工具类:
5.使用方法
6.成果展示
如上面的动图所示,用户手指从左边沿往右滑动,当前页面会跟随手指的移动而移动;
当手指离开屏幕时,会自动检测此刻的状态,如果水平滑动速度>系统最小滑动速度,那么认为这是一个返回触发事件,使用属性动画把页面向右移动出屏幕,并回调 Consumer 的 accept 接口,finish 当前的 Activity。
如果水平滑动速度<系统最小滑动速度,且滑动的最后一个位置的水平坐标大于屏幕宽度的 1/2,那么认为这是一个返回触发事件,执行上述流程。
如果水平滑动速度<系统最小滑动速度,且滑动的最后一个位置的水平坐标小于屏幕宽度的 1/2,则认为用户还想停留在当前页面,使用属性动画把页面向左移动回原点。
7.参考文献
待补充
注意事项 1:需要配置页面的主题是透明背景:
注意事项 2:android:windowBackground 的值设置需为引用,不能直接设置为透明颜色值(#00000000),否则会失效。
版权声明: 本文为 InfoQ 作者【Changing Lin】的原创文章。
原文链接:【http://xie.infoq.cn/article/31dad93f54f7d63c32cc1de32】。文章转载请联系作者。
评论