仿京东首页的下拉刷新

上一篇文章介绍了高仿京东的沉浸式状态栏,可是跟京东首页的头部轮播图相比,依然有三处缺憾:
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.PullDownRefreshLayout
        android:id="@+id/pdrl_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <!-- PullDownScrollView是自定义的滚动视图 -->
        <com.example.event.widget.PullDownScrollView
            android:id="@+id/pdsv_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android: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,下拉刷新的效果见下列组图,其中左图为正在下拉时的截图,右图为松开下拉、开始刷新之时的截图。

转载于:https://my.oschina.net/ouysh1981/blog/1625810

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值