Android App开发进阶与项目实战
上QQ阅读APP看书,第一时间看更新

2.4.3 正常下拉与下拉刷新的冲突处理

电商App的首页通常都支持下拉刷新,比如京东首页的头部轮播图一直顶到系统的状态栏,并且页面下拉到顶后,继续下拉会拉出带有“下拉刷新”字样的布局,此时松手会触发页面的刷新动作。虽然Android提供了专门的下拉刷新布局SwipeRefreshLayout,但是它没有实现页面随手势下滚的动态效果。一些第三方的开源库(如PullToRefresh、SmartRefreshLayout等)固然能让整体页面下滑,可是顶部的下拉布局很难个性化定制,状态栏、工具栏的背景色修改更是三不管。若想呈现完全仿照京东的下拉刷新特效,只能由开发者编写一个自定义的布局控件。

自定义的下拉刷新布局首先要能够区分是页面的正常下滚还是拉到头部要求刷新。二者之间的区别很简单,直观上就是判断当前页面是否拉到顶。倘若还没拉到顶,继续下拉动作属于正常的页面滚动;倘若已经拉到顶,继续下拉动作才会拉出头部提示刷新。所以此处需捕捉页面滚动到顶部的事件,相对应的是页面滚动到底部的事件。鉴于App首页基本采用滚动视图实现页面滚动功能,故而该问题就变成如何监听该视图滚到顶部或者底部。ScrollView提供了滚动行为的变化方法onScrollChanged,通过重写该方法即可判断是否到达顶部或底部。重写后的代码片段如下所示:

(完整代码见event\src\main\java\com\example\event\widget\PullDownScrollView.java)

如此改造一番,只要活动代码设置了滚动视图的滚动监听器,就能由onScrolledToTop方法判断当前页面是否拉到顶了。既然能够知晓到顶与否,同步变更状态栏和工具栏的背景色也就可行了。演示页面拉到顶部附近的两种效果如图2-31和图2-32所示。图2-31为上拉页面使之整体上滑,此时状态栏的背景变灰、工具栏的背景变白;图2-32为下拉页面使之完全拉出,此时状态栏和工具栏的背景均恢复透明。

图2-31 上拉页面时的导航栏

图2-32 下拉页面时的导航栏

成功监听页面是否到达顶部或底部仅仅解决了状态栏和工具栏的变色问题,页面到顶后继续下拉滚动视图要怎么处理呢?一方面是整个页面已经拉到顶了,滚动视图已经无可再拉;另一方面用户在京东首页看到的下拉头部并不属于滚动视图管辖,即使它想拉一下,也是有心无力。不管滚动视图是惊慌失措还是不知所措,恰恰说明它是真的束手无策了,为此还要一个和事佬来摆平下拉布局和滚动视图之间的纠纷。这个和事佬必须是下拉布局和滚动视图的父布局,考虑到下拉布局在上、滚动视图在下,故它俩的父布局继承线性布局比较合适。新的父视图需要完成以下3项任务:

(1)在子视图的最前面自动添加一个下拉刷新头部,保证该下拉头部位于整个页面的最上方。

(2)给前面自定义的滚动视图注册滚动监听器和触摸监听器。其中,滚动监听器用于处理到达顶部和到达底部的事件,触摸监听器用于处理下拉过程中的持续位移。

(3)重写触摸监听器接口需要实现的onTouch方法。这个是重中之重,因为该方法包含了所有的手势下拉跟踪处理,既要准确响应正常的下拉手势,也要避免误操作不属于下拉的手势,比如下面几种情况就要统筹考虑:

① 水平方向的左右滑动,不做额外处理。

② 垂直方向的向上拉动,不做额外处理。

③ 下拉的时候尚未拉到页面顶部,不做额外处理。

④ 拉到顶之后继续下拉,则在隐藏工具栏的同时让下拉头部跟着往下滑动。

⑤ 下拉刷新过程中松开手势,判断下拉滚动的距离,距离太短则直接缩回头部、不刷新页面,只有距离足够长才会刷新页面,等待刷新完毕再缩回头部。

有了新定义的下拉上层布局,搭配自定义的滚动视图就能很方便地实现高仿京东首页的下拉刷新效果了。具体实现的首页布局模板如下所示:

(完整代码见event\src\main\res\layout\activity_pull_refresh.xml)

以上布局模板用到的自定义控件PullDownRefreshLayout和PullDownScrollView代码量较多,这里就不贴出来了,读者可参考本书附带源码event模块的相关源码。运行并测试这个App,下拉刷新的效果如图2-33和图2-34所示。图2-33为正在下拉时的界面,图2-34为松开刷新时的界面。

图2-33 正在下拉时的界面

图2-34 松开刷新时的界面