CoordinatorLayout的使用总结

CoordinatorLayout中的子组件如果不添加相应的依赖关系,那么CoordinatorLayout表现就是一个frameLayout。

CoordinatorLayout不是必须要有NestedScrollingChild。

CoordinatorLayout 本身是不具有滑动功能的。

特性1:子组件靠behavior建立依赖关系

CoordinatorLayout中如果想要实现A子组件始终在B组件的上面,这里的上指的是页面的上下,不是重叠的上下。(因为如果什么都不添加,表现就像frameLayout的子组件的一样:相互重叠),那么就需要A组件或者B组件添加依赖关系,注意,依赖的组件只能是CoordinatorLayout的顶级组件,也就是需要A组件或者B组件添加一个Behavior,即重写layoutDependsOn和onDependentViewChanged两个方法。比如:

public class FollowBehavior extends CoordinatorLayout.Behavior {
  private int targetId;

//从xml中找到添加的需要依赖组件的那个id。
  public FollowBehavior(Context context, AttributeSet attrs) {
      super(context, attrs);
      TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Follow);
      for (int i = 0; i < a.getIndexCount(); i++) {
          int attr = a.getIndex(i);
          if(a.getIndex(i) == R.styleable.Follow_target){
              targetId = a.getResourceId(attr, -1);
          }
      }
      a.recycle();
  }

  @Override// 当依赖的那个view改变时,回调通知这个behavior对应的view应该怎么做.  child 参数就是那个bevior对应的view,也就是你把这个behavior赋予给的那个view。
  public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
       child.setY(dependency.getY()+dependency.getHeight());
      return true;
  }

  @Override// 说明这个behavior对应的view依赖的是哪个view 
  public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
      return dependency.getId() == targetId;
  }
}

子组件靠behavior监听NestedScrollingChild的滑动

首先要注意,子组件并不在NestedScrollingChild里面(即手指触摸的是NestedScrollingChild,没有触摸子组件,但是子组件却能监听手指的滑动,进而做出滑动等相应)。对于多个子组件都设置了bebavior,那么这些子组件都会监听NestedScrollingChild的滑动。还需要注意,如果手指触摸到子组件上滑动,没有在NestedScrollingChild滑动,如果子组件没有实现NestedScrollingChild,那么这时候整个页面是不会动的。所以,如果手指在coordinateLayout的子组件上滑动时,如果想整个布局也滑动,需要这个子组件也实现NestedScrollingChild。为什么呢?因为实现以后,就会把滑动事件交给coordinateLayout,然后coordinateLayout再把事件交给带behavior的子组件。你可能会说,这样的话,coordinateLayout岂不是有两个NestedScrollingChild。可以有两个NestedScrollingChild。下面会说一个view怎么实现NestedScrollingChild。

behavior除了可以建立CoordinatorLayout顶级子组件的依赖关系外(layoutDependsOn和onDependentViewChanged两个方法),顶级子组件还可以使用behavior监听NestedScrollingChild实现类的滑动,当然,需要CoordinatorLayout中有NestedScrollingChild。 behavior监听NestedScrollingChild的滑动,依靠的是bahavior的三个方法(不需要在bahavior中建立依赖就能监听):

//这里返回true,NestedScrollingChild才会给该behvior对应的view分发事件。
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes);

public void onNestedPreScroll(View target, int dx, int dy, int[] consumed);

public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed);

当我们滚动页面时,NestedScrollingChild接收到了事件,知道了手指在x 和y方向滑动的距离,然后NestedScrollingChild会把这个事件通过

public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow);

方法分发给CoordinatorLayout,继而分发给behavior,即,调用behavior onNestedPreScroll()方法。dispatchNestedPreScroll()中的dx就是这次操作,手指在x方向的距离。那么consumed数组是什么呢?注解上说了,这是一个Output 数组,也就是说会传入一个空数组。bahavior的onNestedPreScroll()方法拿到这个空数组后,根据onNestedPreScroll()的逻辑,即在x,y方向消费了多少,把消费的数值传到consumed数组中。这样,NestedScrollingChild就知道NestedScrollingParent消费了多少了。然后NestedScrollingChild会将手指在x方向的距离减去NestedScrollingParent在x方向消费的距离得到这次操作剩余的距离(即NestedScrollingParent可能没消费完全),然后NestedScrollingChild会自己消费掉剩下的距离。当然,如果,behavior中没有重写onNestedPreScroll()方法,那么dispatchNestedPreScroll()会返回false,意味着NestedScrollingChild会消费掉这次操作手指滑动的所有距离。
等到NestedScrollingChild消费掉它应该消费的距离后,会调用

 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow);

通知一下CoordinatorLayout,继而通知behavior,即,调用behavior的onNestedScroll()方法。dispatchNestedScroll()中的dxConsumed为NestedScrollingChild在x方向已经消费的距离。这个参数和behavior的onNestedScroll()中的dxConsumed参数是一样的,都是表示NestedScrollingChild在x方向已经消费的距离。这样behavior就可以根据这个距离来让behavior对应的view是不是也消费相同的距离来协同滑动,或其他数值的距离。

所以,behavior中重写onNestedPreScroll()方法,可以设置一些条件,在某些条件下,让手指的滑动距离被behavior对应的view消费完全,NestedScrollingChild就不再参与消费了

behavior中重写onNestedScroll()方法,记住,回调behavior此方法时,NestedScrollingChild已经完成了滑动距离的消费。所以,使用这个方法可以让behavior对应的view也滑动某些距离和NestedScrollingChild保证协同滑动。

coordinateLayout 中搭配viewPager

coordinateLayout中含有viewPager,和一些其他带behavior的顶级子view。如果viewPager中含有NestedScrollingChild,那么coordinateLayout中的顶级子view是可以接受到NestedScrollingChild分发的滑动事件的。

不过,对于flinger滑动可能有些问题,可以参考:

http://blog.csdn.net/bigggfish/article/details/53585783

一个view怎么实现NestedScrollingChild

可以看这个库 的NestedLinearLayout类。
第一步,让这个view实现NestedScrollingChild的接口。很容易实现,都是调用的NestedScrollingChildHelper的工具方法。

第二步,如果手指在这个view上滑动,怎么把滑动事件交给coordinateLayout处理。事件来到这个view了,我们需要调用onInterceptTouchEvent()拦截MOVE事件(注意虽然在onInterceptTouchEvent不让down事件返回true,但是需要在down事件到来时,调用NestedScrollingChild接口方法startNestedScroll
(),第一步实现好了,这个方法的作用就是看看coordinateLayout的各个bahavior有没有能处理这个动作的,即bahavior的onStartNestedScroll
是不是返回true)。我们知道拦截了MOVE,之后这个手势动作剩下的move和up事件就不会往下传了,而是马上会回调该view的onTouchEvent()方法,处理MOVE。怎么处理呢?很简单,我们只需要调用dispatchNestedPreScroll()将该事件分发到coordinateLayout就可以了。coordinateLayout 会分发给各个带bebavior的
子view。当然可能当下的这个view就实现了behavior接口,即该view的bahavior会处理这个move动作。dispatchNestedPreScroll()这个我们在第一步时已经实现了,所以直接拿来用即可。

参考 :这个库
这个

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容