效果图如下
效果图首先不说Behavior,但说这个效果,用监听滑动手势也能做,但岂不是很麻烦,而且也没法复用,Behavior就是解决这些问题的.
Behavior是Android新出的Design库里新增的布局概念。Behavior只有是CoordinatorLayout的直接子View才有意义。可以为任何View添加一个Behavior。Behavior是一系列回调。让你有机会以非侵入的为View添加动态的依赖布局,和处理父布局(CoordinatorLayout)滑动手势的机会,使用户的界面交互更加便捷,
使用方法:
自定义Behavior,你需要继承CoordinatorLayout.Behavior,然后实现他的一个构造方法,必须是有参的构造,因为会用到反射
publicbuttomBehavior(Context context,AttributeSet attrs) {
super(context,attrs);
}
return c.newInstance(context, attrs)//这是源码中的一句代码
然后你就可以为任何一个View设置这个Behavior了,当然目前没什么效果的,为一个view设置Behavior有俩种方法
方法一:xml设置
像下图这样把这个类的全类名设置到该View
xml设置方法二:注解设置
该方法一般用为自定义的控件,或者官方api中用的比较多,如下图
注解设置我们这里使用第一种方法
Behavior实现
那么自定义一个Behavior之后,后续的效果该如何实现呢,我们看下Behavior的源码的方法
onAttachedToLayoutParams 被绑定到一个layoutParams的回调
onDetachedFromLayoutParams 解绑layoutParams的回调
onInterceptTouchEvent onTouchEvent 这俩个我们很熟悉,触摸事件的相关拦截
getScrimColor 为相关的view不相关的区域蒙纱(主要为了在控件交互的时候引起用户注意力)
getScrimOpacity 蒙纱的一个透明度(范围0-1);
layoutDependsOn 关联一个控件(这个常用)
onDependentViewChanged 当关联的控件变化时的回调
onDependentViewRemoved 当关联的控件移除时的回调
onMeasureChild 测量子View
onLayoutChild 布局子view
setTag getTag 将一个obj对象与子View的layoutparams关联起来
onStartNestedScroll 嵌套滑动开始时,回调
onStopNestedScroll 嵌套滑动结束时,回调
onNestedScrollAccepted 当一次嵌套滑动被CoordiantorLayout识别并确定时,进行回调
onNestedScroll 嵌套滚动正在进行中并且绑定目标childView已经开始滚动或者被CoordinatorLayout接受后试图滚动
onNestedPreScroll 嵌套滚动正在准备更新进度,并且是在绑定目标childView已经出现滚动距离之前,回调
onNestedFling 当嵌套滚动的childView正在开始fling或者一个动作确认为fling
onNestedPreFling 当滑动嵌套childView检测到适当的条件,马上开始一次fling事件前回调
onRequestChildRectangleOnScreen 当Behavior关联的对象想要定位到特定的矩形时,回调
onRestoreInstanceState 需要恢复临时信息
onSaveInstanceState 临时保存信息
getInsetDodgeRect 当View设置回避属性时,回调(回避就是,当一个view移动过来,他需要让位置)
嗯,看完这么多方法我也蒙了,这是要干啥?其实一般情况也用不到这么多,重写其中几个常用的方法即可,当然需求如果特别复杂,就需要用到上面的一系列方法,很多我也没用过
实现一个Behavior一般来说也有俩种方法,即俩种套路
套路一:
关联子view进行交互,子View的一举一动将影响他的一举一动
一般如下实现这俩个方法即可
套路一套路二:
根据父布局的滑动一系列监听来完成相关的运动
一般来说你可能会用到上面的那一堆滑动相关的回调,但如果你的滑动不是那么复杂其实也不是全部有用,我们看下几个方法
onStartNestedScroll
该方法一般都要重写,它判断你是否要消费本次滑动(或者说在神们情况下消费)
axes== ViewCompat.SCROLL_AXIS_HORIZONTAL 表示是水平方向的滑动
axes == ViewCompat.SCROLL_AXIS_VERTICAL 表示是竖直方向的滑动
onNestedPreScroll
这个方法是准备消费滚动距离之前的回调,该方法主要用来处理你要消耗哪些dy,dx的,消耗掉的意思,就是自己去执行scrollBy.这个根据具体情况去处理
dy>0向上滑动,dy<0向下滑动
consumed是一个消费距离的数组
onNestedScroll
嵌套滚动正在进行中并且绑定目标childView已经开始滚动或者被CoordinatorLayout接受后试图滚动,一时就是正在滑动的时候的回调
dxConsumed dyConsumed 这俩个代表横向,竖向消耗的dy,dx
dxUnconsumed dyUnconsumed 这俩个代表横向,竖向消耗的dy,dx(但不是本次操作产生的,是用户要求的)
onNestedFling
这个是当进行一次快速滑动的回调,很多情况也是要做一定处理的
velocityX velocityY 这俩个是代表水平,垂直的互动速度,速度为0就说明这次快速的脱手滑动停止了
consumed 标示子view是否消耗了这次fling
返回值标示是否拦截fling
仿知乎的实现
回到正题,模仿知乎的一个效果,当然有一点是不一样的,知乎的fb应该是个位移的动画,我这里做成了一个缩放的动画,没什么区别,网上的其他的相关博客基本都是仿知乎...
我们来分析
1,整个界面其实就是一个底部导航栏,加上一个fb,再加上一个toolbar,很简单,其他博客的写法都是一个activity完成的,其实考虑的正常的小木中不会这么干的,导航栏一般都是和fragment合作的,所以我的写法是 底部导航+toolbar+fragment,下面是布局:
个人喜欢截图,所以就把这些东西折叠起来了,我们看布局结构就可以,里面是神们东西不用脑子也可以想出来,导航栏偷懒使用了RadioGroup..效果是没什么区别的.
注意:下图是上图中include的布局,也就是动态添加fragment的布局,这里有一点特殊的,不是说只能是可以滑动的布局吗,为神们framelayout也能设置behavior并且生效,事实证明是可以的,只要这个东西是可以滑动的即可,他监听的是这个区域的滑动,而不是view的.所以请放心使用fragment,并不会有神们问题,你放一个viewpager,viewpager中再放listview都是可以的,只要添加behavior的viewGroup最终可以滑动就会有效果的
2,然后我们的这个fb貌似只能放到activity了,开始我想放到第一个fragment的,但是behavior的使用必须是直接的子view,防盗fragment会失效,我目前不知到有没其他方法,求告之,...只能放到activity根据导航栏的切换来显示影藏这个东西
3,然后就是动态的添加,替换fragment,没什么好说的,主要来看俩个behavior,我个人喜欢用第一种套路写法,事实证明一般情况第一种情况更加好用,因为一般的控件交互都会有一个参照物,当然这个参照物的behavior一般来说是套路二写的.
第一个导航栏的buttom是根据appbarlayout的反方向滑动,所以很简单这么写就可以了
第二个fb的也是根据appbarlayout来做的,appbarlayout向上滑动的时候影藏掉,向下滑动的时候显示出来
4,然后将这俩个behavior设置给相应的view即可,有没有很简单,如果要根据recycleview的滑动手势来做,那简直很恶心
网友评论