专栏名称: 鸿洋
你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。
目录
相关文章推荐
鸿洋  ·  Google 为何设计了如此难用的 ... ·  2 天前  
stormzhang  ·  时间不多了 ·  3 天前  
鸿洋  ·  Android14 WMS/AMS ... ·  3 天前  
stormzhang  ·  真正该刺激的是收入 ·  4 天前  
鸿洋  ·  一款高效的HarmonyOS工具包 ·  4 天前  
51好读  ›  专栏  ›  鸿洋

阻尼效果 | 自定义实现MIUI的拖动视差效果

鸿洋  · 公众号  · android  · 2017-07-07 07:30

正文

每日推荐


用nodejs(express+react)搭建的极简的服务器,给定一个url就返回一个特定的Json数据,提供给客户端开发同学用的模拟Json服务器接口的项目,项目尽可能的简单,核心代码只有100多行,简单而实用,方便扩展。


在平时开发过程中,还是挺有用的,接口返回数据定义完成就可以测试啦~


https://github.com/heimashi/easy_mock_api


本文作者


本文由xiaoyanger授权发布。

xiaoyanger的博客地址:

http://www.jianshu.com/u/25c3b13f87ce


在MIUI上有一些界面在拖动的时候有一个视差效果:



在可以滚动的视图中,内容滚动到顶部时继续下拉,整个视图就有一个竖直方向拉伸的视差效果。滚动到底部继续上拉,也有同样的效果。


滚动视图可能是ScrollView、RecyclerView,要实现这样的效果,需要自定义并拦截Touch事件,重新处理事件逻辑。


以RecyclerView为例,我们自定义一个ParallaxRecyclerView,复写onInterceptTouchEvent方法:



滚动RecyclerView到达顶部或者底部继续拖动时,需要拦截Touch事件。所以在MotionEvent.ACTION_MOVE时需要判断当前RecyclerView是否在顶部或者底部。需要注意的是,当RecyclerView中的item没有填充满整视图时,RecyclerView的状态既是在顶部也是在底部。



mActivePointerId表示在多点触控是当前活动手指的id,mInitialMotionY为手指按下时的Y坐标。


当达到顶部或底部继续拖动时,根据当前的位置(isScrollToTop()、isScrollToBottom())和ACTION_MOVE时的移动距离yDiff来判断是否需要拦截:在顶部时向上拖动并且yDiff>mTouchSlop就需要拦截,底部时向下拖动同样yDiff>mTouchSlop也需要拦截,同时在顶部和底部时满足Math.abs(yDiff)>mTouchSlop也需要拦截。


需要拦截都是在没有被拖动(!isBeingDragged)的情况下。


RecyclerViev既没有在顶部也没有在底部时,说明item滚动到中间,可以上下继续滚动,不需要拦截,交给super.onInterceptTouchEvent(event)来处理。同时其它不需要拦截的情况也都交给super来处理。


onSecondaryPointerUp(event)为当第二个手指离开屏幕是需要重新设置mActivePointerId:



拦截到TouchEvent,在onTouchEven中处理,实现拖动视差效果:



代码虽然有点长,但是逻辑很简单,在拦截到ACTION_MOVE事件后,同样根据顶部或底部位置以及滚动的距离mDistance来确定是否消费掉该事件。不需要消费的直接给`super.onTouchEvent(event)来处理,需要消费的话根据mDistance来计算出缩放的比例mScale,再通过pull(mScale)和push(mScale)来缩放。



mScale的计算是一个二次函数,当拖动距离越大时,mScale的变化程度越小,这样使得拖动时有一个张力效果。



在ACTION_UP时,需要将缩放的视图通过动画还原到初始状态。这里也需要判断位置,因为不同位置的的缩放中心点不一样。同时即在顶部也在底部时是根mDistance的正负值来判断拖动的方向。



这样就OK了,如果需要实现ScrollView、ListView、GridView也是一样的逻辑,源码中已经有了ParallaxScrollView的实现,看下最终效果图:


  • ParallaxRecyclerView:



  • ParallaxScrollView



源码:

https://github.com/xiaoyanger0825/Parallax


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


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