0°

Android 改造SwipeRefreshLayout 支持上拉加载

内容预览:
  • (1)滑动流程  子view获取到点击事件后,询问父亲是否需要配合滑...~
  • 现在我们想加上上拉刷新功能,可以反着做,给下方加一个可拉动的控件(...~
  • 为了能兼顾上层,我们再外面还加了常规的CoordinatorLayout和AppBarLayo...~

始发于微信公众号: 鸿洋

每日推荐


看到这个文章我才想起来,今天推荐一个项目,是我的一位好朋友之前在创业公司的一个项目,后来项目失败了,经允许后将源码分享出来了,该项目也对SwipeRefreshLayout进行了扩展,支持了上拉,如果有实际需求,不妨也试下这个(项目质量非常高)。


https://github.com/pinguo-sunjianfei/Android-Application-ZJB


ps:该项目服务端已经停了,所以只能看代码了,运行不起来了~~


本文作者


本文由Get_Zoom投稿。

Get_Zoom的博客地址:

http://blog.csdn.net/Get_Zoom


1

NestedScrolling机制


之前笔者在设计的时候,想在ViewPager的页面上实现仿微信的左滑删除,但是怎么都实现不了,因为其中跟ViewPager的滑动冲突了,当时才疏学浅(现在也是),进了很多坑,比如滑动的拦截、滑动事件在Down之后会跳过判断等,在没有系统学习过这方面知识的情况下以大败告终。 


所以,谷歌人性化地推出了这个机制,滑动之前和父控件商量一下,一切多么融洽,和之前盲人摸象的方式相比人性化多了。


(1)滑动流程 


子view获取到点击事件后,询问父亲是否需要配合滑动,然后每一次滑动之前都会询问父亲,并记录下父亲消耗的滑动距离,在上面完成后才进行自己自身的滑动。


(2)接口


NestedScrollingChild


Android 改造SwipeRefreshLayout 支持上拉加载


NestedScrollingParent


Android 改造SwipeRefreshLayout 支持上拉加载


(3)帮助类


NestedScrollingChildHelper 
NestedScrollingParentHelper


故名思义,上面的帮助类帮助我们处理了上面父子接口的方法。


它们帮助我们实现了逻辑上的方法,在一些情况下我们只希望处理子接口或者父接口,为了对接可以在另一个接口使用帮助类(比如下面的实例,改造SwipeRefreshLayout,我们更希望作为父亲处理子view事件而滑动自身,对于上层组件(父)不是很关心,就可以使用NestedScrollingParentHelper来方便编程。


借用网上的一张图,可以看到两个接口之间的对应关系:


Android 改造SwipeRefreshLayout 支持上拉加载


图片来源:https://segmentfault.com/a/119000000287365



2

实例演示:改造SwipeRefreshLayout


(1)目的

SwipeRefreshLayout就是一个实现了NestedScrolling机制的控件,可以方便的实现下拉刷新。


现在我们想加上上拉刷新功能,可以反着做,给下方加一个可拉动的控件(小圆圈),然后处理它的滑动事件。为了能兼顾上层,我们再外面还加了常规的CoordinatorLayout和AppBarLayout作为测试。


成果: 

Android 改造SwipeRefreshLayout 支持上拉加载


(2)准备工作 

改造之前当然要先把人家之前的成果准备好。 

Android 改造SwipeRefreshLayout 支持上拉加载 

首先当然是把我们的SwipeRefreshLayout移过来,可以换一个名字避免以后的冲突。


然后布局中要用到两个控件,一个是CircleImageView,也就是显示的小圆圈,附带阴影功能;一个是MaterialProgressDrawable,用于在CircleImageView显示进程(颜色滑动)。


在移动的时候SwipeRefreshLayout会报错,报错时把东西移动过来就行了。

 
然后阅读源码,我们暂时只处理NestedScrolling机制,所以一般的移动流程比如onTouchEvent可以先放着,以后为了和其他不带NestedScrolling控件兼容的时候再改进。


(3)开始改造工作 

1.参数测量 


一个主要的问题就是,我们下面的圆圈(加载圈,以下简称圆圈)要放在哪?


原生的直接放在中间然后上去一个圆圈身位的地方,所以下面圆圈水平位置一样,竖直的话就放在屏幕下方。


综合测试出这样的距离比较好:


Android 改造SwipeRefreshLayout 支持上拉加载


所以相应的位置放置我们就这样:


Android 改造SwipeRefreshLayout 支持上拉加载


2.作为父控件配合滑动


  • a.是否配合滑动


Android 改造SwipeRefreshLayout 支持上拉加载


这里我们只增加了一个上拉刷新标志位


Android 改造SwipeRefreshLayout 支持上拉加载


这里也是,只是增加了mTotalUnconsumedBottom ,这是我们上拉刷新的未消费路程。


  • b.滑动之前


我们可以看到源码中的onNestedPreScroll有这么一段处理:


Android 改造SwipeRefreshLayout 支持上拉加载


在滑动前先判断,我们未消费滑动路程是否还有,有则判断方向,如果是滑动的反方向,也就是我们再下拉刷新一半的时候又往回拉,这时做出处理,选择消费当前滑动路程。


所以我们可以写出下方的拖动预处理:


Android 改造SwipeRefreshLayout 支持上拉加载


这里有个坑要提醒下,一开始笔者自作聪明,觉得consumed参数应该传绝对值,导致后来往回滑的时候子控件跑得飞快(可以想想为什么),所以这里消费了负的路程就传回负的路程,可以看看源码中NestedScrollingChildHelper的实现。


  • c.正式滑动


这个反而比较容易,只需要加上判断当前子控件还能不能往上滑。


Android 改造SwipeRefreshLayout 支持上拉加载


滑动处理:


Android 改造SwipeRefreshLayout 支持上拉加载


大概解释一下,我们的滑动时分段的,在mTotalDragDistance滑动之前是线性的,在这之后会做一个加速的处理,最多延伸一个mSpinnerOffsetEnd

在实际的view位置改变中,我们使用的是

setTargetOffsetTopAndBottomForBottom     (targetY-mCurrentTargetOffsetBottom, true);

这个方法,里面是采用

ViewCompat.offsetTopAndBottom

来改变view的位置的。


  • d.结束滑动


如果手指离开的时候,拖动距离不为零,那么我们要做判断,做出相应的处理


Android 改造SwipeRefreshLayout 支持上拉加载


可以看到主要有两种处理,以mTotalDragDistance为界限,超过这个滑动距离我们就显示刷新,没有的话就动画回到原点。


3.作为子控件配合滑动 

我们知道,AppBarLayout和CoordinatorLayout会配合滑动,子view往上滑的时候会隐藏,如果不做处理,在下端圆圈滑动到一半的时候往回滑会把AppBar又拖出来,消费滑动事件,所以我们选择拦截,在下部圆圈滑动的时候优先处理滑动:



Android 改造SwipeRefreshLayout 支持上拉加载



到这里,我们的控件就基本完成了,当然谷歌出版的控件,动画效果是不能少的,它的美观也体现在这里,由于基本是能模仿的,所以这里不再多讲。这个控件的改造主要麻烦在它的动画衔接以及滑动处理机制(加速等),剩下的都很好理解,建议大家动手试一试。


项目地址:

https://github.com/SGZoom/DailyWidget/tree/master/widgetpro


文章跟代码可能包含很多不足之处,欢迎大家帮忙指出错误与不足,谢谢~


参考文章:

  • https://segmentfault.com/a/1190000002873657 

  • http://blog.csdn.net/al4fun/article/details/53888990

ZZS

3月29日,100offer 邀请了被称作「架构师的摇篮」的阿里中间件参加知乎 Live。

阿里中间件承载了世界上最有挑战的场景,应对了一次次双十一的流量洪峰,他们对人才的要求指引优秀架构师之路的方向。

扫描二维码,参与 Live 会让你了解怎么样的架构师才能胜任顶尖团队中的工作

Android 改造SwipeRefreshLayout 支持上拉加载


如果你有想学习的文章直接留言,我会整理征稿。如果你有好的文章想和大家分享欢迎投稿,直接向我投递文章链接即可。


欢迎长按下图->识别图中二维码或者扫一扫关注我的公众号:

以上就是:Android 改造SwipeRefreshLayout 支持上拉加载 的全部内容。

本站部分内容来源于互联网和用户投稿,如有侵权请联系我们删除,谢谢。
Email:[email protected]


0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论