写在前面
熟悉layout_behavior的朋友都知道,它是CoordinatorLayout的重要属性。不过,你该不会以为它只能用在NestedScrollingChild上吧?如果你真这么觉得,它可会很伤心的:人家才没有这么弱呢。
其实它的能力远远不止这些。这里和大家分享一个 Demo 和心得。
效果图
这次仿的是“下拉回退”效果,来自 https://github.com/nickbutcher/plaid,
这个项目有必要学习一下,堪称神交互。

我的效果:

源码
本来想研究“过场动画”,所以名字取成了ShareElement,其实是Behavior的Demo,不要在意这些细节。
https://github.com/fashare2015/ShareElementDemo
灵感来源
BottomSheetBehavior
之前在掘金上发了处女作——Android 简易悬停抽屉控件 —— 仿知乎收藏夹。结果分分钟被打脸,这分明就有官方控件啊orz。百度了才知道
support包里有这玩意——BottomSheetBehavior。也正感谢它,有了今天这篇博客。
它的用法是这样的:
在需要的控件上加上一行app:layout_behavior="@string/bottom_sheet_behavior"。搞定了,你的LinearLayout已经变成一个底部抽屉控件了。。。这也太屌了吧。。。
那我们的demo呢,也跟这个类似。
<android.support.design.widget.CoordinatorLayout> <LinearLayout app:layout_behavior="@string/bottom_sheet_behavior"/> ... </LinearLayout> </android.support.design.widget.CoordinatorLayout>
Plaid 的“下拉回退”效果
如前面效果图所示,我主要模仿了,下拉回退和过场动画两个效果。
#实现
Plaid里面是通过自定义View来实现,那我这里呢用Behavior试一下,能更好的复用。
Behavior 的接口
从接口看,它更像是一个轻量级的 View, 有一些类似 View 的接口:
View 的绘制
onMeasureChild
onLayoutChild
View 的事件分发
onInterceptTouchEvent
onTouchEvent
child 间的依赖
layoutDependsOn
onDependentViewChanged
child 的嵌套滑动响应
onStartNestedScroll
onNestedPreScroll
onNestedScroll
onStopNestedScroll
…
网上看到的资料中所介绍的更多的为NestedScroll这一块。而对于绘制和事件分发避而不谈,使得Behavior少了许多应用场景。事实上,NestedScroll使用起来更有局限性,它要求应用该Behavior的View必须implement NestedScrollingChild。反观绘制和分发,基于它们的Behavior可以应用在所有的View上,是自定义View的一种更轻量的实现。
behavior 定义与使用
定义两个Behavior:
FollowBehavior:一个 “紧贴联动” 的 Behavior,使得 RecyclerView 移动时,ImageView 紧贴着它。这是一个典型的
child 间的依赖的场景。DragDismissBehavior:拖动时拦截事件,使得 RecyclerView 本体移动(而非内部 scroll)。移动到一定距离时,finish Activity。这里用到了
事件分发和NestedScroll两类回调。
注意:RecyclerView为NestedScrollingChild,因此下拉回退很流畅。但是,事实上,DragDismissBehavior还可以用在非NestedScrollingChild上,例如ListView、ScrollView等,仍然可以正常的下拉回退。只不过NestedScroll的回调不在响应,流畅度有些下降。亲们可以自己试一下。
<!-- activity_detail --> <android.support.design.widget.CoordinatorLayout> <ImageView app:layout_behavior=".behavior.FollowBehavior"/> <android.support.v7.widget.RecyclerView app:layout_behavior=".behavior.DragDismissBehavior"/> </android.support.design.widget.CoordinatorLayout>
代码实现
主要有这几块:
事件分发:用
mViewDragHelper处理拖动事件,参考:滑动:smoothScrollTo(),涉及 Scroller 类的使用
Behavior 的 NestedScroll 相关回调:也不复杂,需要理解
NestedScrollingParent和NestedScrollingChild。参考:
代码就不贴了,主要是把接口理清楚,像onMeasure()->onLayout()->onDraw()一样,挨个往里填实现就是了。
有兴趣可以看看,自认为可读性还是可以的,嘿嘿。
作者:梁山boy