上一篇文章介绍了高仿京东的沉浸式状态栏,可是跟京东首页的头部轮播图相比,依然有三处缺憾:
1、京东的头部Banner上方,除了有悬浮着的状态栏,状态栏下面还有一行悬浮工具栏,内嵌扫一扫图标、搜索框,以及消息图标;
2、把整个页面往上拉,状态栏的背景色从透明变为深灰,同时工具栏的背景也从透明变为白色;
3、页面下拉到顶后,继续下拉会拉出带有“下拉刷新”字样的布局,此时松手则会触发页面的刷新动作;
上面第一点的状态栏和工具栏悬浮效果,都有对应的解决办法;第二点的状态栏和工具栏背景变更,也存在可行的解决方案。倒是第三点的下拉刷新,以及第二点的上拉监听,却不容易实现。

虽然Android提供了专门的下拉刷新布局SwipeRefreshLayout,但它并没有页面随手势下滚的效果。一些第三方的开源库如PullToRefresh、SmartRefreshLayout固然能让整体页面下滑,可是顶部的下拉布局很难个性化定制,至于状态栏、工具栏的背景色修改更是三不管。因此若想呈现完全仿照京东的下拉刷新特效,只能由开发者编写一个自定义的布局控件了。
自定义的下拉刷新布局,首先要能够区分是页面的正常下滚,还是拉伸头部要求刷新。二者之间的区别很简单,直觉上看就是判断当前页面是否拉到顶了。倘若还没拉到顶,继续下拉动作属于正常的页面滚动;倘若已经拉到顶了,继续下拉动作才会拉出头部提示刷新。所以此处得捕捉页面滚动到顶部的事件,相对应的则是页面滚动到底部的事件。鉴于App首页基本采用滚动视图ScrollView实现页面滚动功能,故而该问题就变成了如何监听该视图滚到顶部或者滚到底部。正好ScrollView提供了滚动行为的变化方法onScrollChanged,通过重写该方法即可判断是否到达顶部或底部,重写后的代码片段如下所示:

    protected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);boolean isScrolledToTop;boolean isScrolledToBottom;if (getScrollY() == 0) {// 下拉滚动到顶部isScrolledToTop = true;isScrolledToBottom = false;} else if (getScrollY() + getHeight() - getPaddingTop() - getPaddingBottom() == getChildAt(0).getHeight()) {// 上拉滚动到底部isScrolledToBottom = true;isScrolledToTop = false;} else {// 未拉到顶部,也未拉到底部isScrolledToTop = false;isScrolledToBottom = false;}if (mScrollListener != null) {if (isScrolledToTop) {// 触发下拉到顶部的事件mScrollListener.onScrolledToTop();} else if (isScrolledToBottom) {// 触发上拉到底部的事件mScrollListener.onScrolledToBottom();}}}private ScrollListener mScrollListener;// 设置滚动监听器的实例public void setScrollListener(ScrollListener listener) {mScrollListener = listener;}// 定义一个滚动监听器,用于捕捉到达顶部和到达底部的事件public interface ScrollListener {void onScrolledToBottom();void onScrolledToTop();}

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

然而成功监听页面是否到达顶部或底部,仅仅解决了状态栏和工具栏的变色问题。因为页面到顶时继续下拉,ScrollView要怎么处理?一方面是整个页面已经拉到顶了,造成ScrollView已经无可再拉;另一方面,用户在京东首页看到的下拉头部,其实并不属于ScrollView管辖,即使ScrollView想拉这个头部兄弟一把,也只能有心无力。不管ScrollView是惊慌失措,还是不知所措,恰恰说明它是真正的束手无策了,为此还要一个和事佬来摆平下拉布局和滚动视图之间的纠纷。
这个和事佬必须是下拉布局和滚动视图的上级布局,考虑到下拉布局在上,而滚动视图在下,故它俩的上级布局继承线性布局LinearLayout比较合适。新的上层视图需要完成以下三项任务:
一、在下层视图的最前面自动添加一个下拉刷新头部,保证该下拉头部位于整个页面的最上方;
二、给前面自定义的滚动视图注册滚动监听器和触摸监听器,其中滚动监听器用于处理到达顶部/底部的事件,触摸监听器用于处理下拉过程中的持续位移。
三、重写触摸监听器接口需要实现的onTouch函数,这个是重中之重,因为该函数包含了所有的手势下拉跟踪处理。既要准确响应正常的下拉手势,也要避免误操作不属于下拉的手势,比如下面几种情况就得统筹考虑:
1、水平方向的左右滑动,不做额外处理;
2、垂直方向的向上拉动,不做额外处理;
3、下拉的时候,如果尚未拉到页面顶部,也不做额外处理;
4、拉到顶之后继续下拉,则隐藏工具栏的同时,还要让下拉头部跟着往下滑动;
5、下拉刷新过程中松开手势,判断下拉滚动的距离,距离太短则直接缩回头部、不进行页面刷新;只有距离足够长,才能触发页面刷新动作,等待刷新完毕再缩回头部。

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/white"><!-- PullDownRefreshLayout是自定义的下拉上层布局 --><com.example.event.widget.PullDownRefreshLayoutandroid:id="@+id/pdrl_main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!-- PullDownScrollView是自定义的滚动视图 --><com.example.event.widget.PullDownScrollViewandroid:id="@+id/pdsv_main"android:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><!-- 此处放具体页面的布局内容 --></LinearLayout></com.example.event.widget.PullDownScrollView></com.example.event.widget.PullDownRefreshLayout><!-- title_drag.xml是带搜索框的工具栏布局 --><include layout="@layout/title_drag" />
</RelativeLayout>

以上布局模板用到的PullDownRefreshLayout和PullDownScrollView,因为代码量较多,这里就不贴出来,有需要的朋友请留下邮箱,我单独发过去。运行改造后的测试App,下拉刷新的效果见下列组图,其中左图为正在下拉时的截图,右图为松开下拉、开始刷新之时的截图。

点此查看Android开发笔记的完整目录

__________________________________________________________________________
本文现已同步发布到微信公众号“老欧说安卓”,打开微信扫一扫下面的二维码,或者直接搜索公众号“老欧说安卓”添加关注,更快更方便地阅读技术干货。

Android开发笔记(一百六十四)仿京东首页的下拉刷新相关推荐

  1. Android开发笔记(六十四)网页加载与JS调用

    内置浏览器 网页视图WebView 如果一个网站已经有现成的网页及业务逻辑,那么使用WebView将其内嵌到app中,省去了app重画页面与http通信的事情,无疑是更经济的做法.WebView就是A ...

  2. Android开发笔记(七十四)布局文件优化

    include/merge 布局优化中常常用到include/merge标签,include的含义类似C代码中的include,意思是直接把指定布局片段包含进当前的布局文件.include适用于多个布 ...

  3. Android开发笔记(六十六)自定义对话框

    AlertDialog Android中最常用的对话框是AlertDialog,它可以完成常见的交互操作,如提示.确认.选择等等,然后就是进度对话框ProgressDialog(参见< Andr ...

  4. Android开发笔记(六十八)工程库打包

    写好一个Android模块,比如说一个自定义控件或某个功能的sdk,然后开放出来给别人使用,就得通过某种方式把源码提供给对方.常见的打包方式有: 一.直接给源码,由开发者把代码加入到自己的工程中 该方 ...

  5. Android开发笔记(五十四)数据共享接口ContentProvider

    ContentProvider 前面几节介绍了进程间通信的几种方式,包括消息包级别的Messenger.接口调用级别的AIDL.启动页面/服务级别的Notification,还有就是本节这个数据库级别 ...

  6. Android开发笔记(六十五)多样的菜单

    菜单Menu Android的菜单分为两类:选项菜单和上下文菜单,默认使用选项菜单.菜单的布局文件存放在res/menu目录下,使用ADT新建一个Android工程,首页代码MainActivity中 ...

  7. Android开发笔记(二十四)res目录的结构与配置

    res目录结构 res是Android项目工程中存放各类的目录,主要包括布局.图形与配置等等.res的子目录主要有: anim : 存放动画的描述文件 drawable : 存放各类图形的描述文件,包 ...

  8. 仿京东天猫的下拉刷新

    http://www.jianshu.com/p/9daaa87045d0 快速仿写京东.天猫下拉刷新 =.=## 这次跟大家分享一下下拉刷新,之前我们的公司的项目一直都是使用SwipeRefresh ...

  9. Android开发笔记(六十二)HTTP数据格式的解析

    json解析 android有两种主流的json解析方案,一种是sdk自带的由Google提供的json(包名前缀为org.json),另一种是Alibaba提供的第三方jar包fastjson(包名 ...

最新文章

  1. 分享.NET开发中经常使用到的代码片段 完全从实际项目中提取出来,也可被反反复复的重复借用...
  2. keil 查看 stm32 io波形_如何系统地入门学习stm32?
  3. wireshark 十六进制过滤_CTF流量分析之wireshark使用
  4. P2P中的NAT穿越方案简介
  5. VC2008以资源形式实现多语言版本
  6. 开源能带来什么?听听入选2021胡润U30创业领袖榜单的90后怎么说
  7. 一个CSharp类代码,让你的窗体显示的更酷(转)
  8. 性能测试工具选型原则
  9. ElasticSearch Group by Multi Field,多字段聚合
  10. IPD开发流程TR1-TR6各个阶段简介
  11. 女孩子没有事业就只能痛苦
  12. 国庆节快到了,用 Python 给自己制作国旗头像,其实很简单。
  13. Excel去掉下划线首字母小写的公式
  14. 为什么要用大写L替换小写L(l),idea提醒literal ‘xxx‘ ends with lowercase ‘l‘
  15. 千亿级宠物赛道,卖蚊香的朝云能“掘金”多少?
  16. PyEcharts 基本图表之雷达图
  17. BCEWithLogitsLoss= BCELoss + Sigmoid
  18. 大数据云原生能力成熟度模型,重磅发布!
  19. 乐观处世,诚实做人,不骄不躁,积极进取; 勇于创新,踏实实现,谨慎规划,付诸实践; 事在人为...
  20. ZHA Coordinator 如何控制ZLL Light/Philips Hue Light

热门文章

  1. Leetcode每日一题:169.majority-element(多数元素)
  2. 吴恩达机器学习作业Python实现(二):logistic回归
  3. 了解一下Bootstrap
  4. python真的那么火还是炒作_Python语言为什么会这么火?老男孩python
  5. mysql 5.7日志的种类_MySQL中的六种日志类型的介绍
  6. 防震计算机主机,一种防震计算机主机的制作方法
  7. 无盘服务器集群,镜像(无盘柜)-单活集群解决方案
  8. 【第4篇】Python爬虫实战-抓取B站弹幕视频
  9. java语言与c++语言相比_最突出的特点是_Java 语言与C++语言相比,最突出的特点是( )。_学小易找答案...
  10. php fopen html,PHP fopen和fwrite函数实现创建html页面_PHP教程