CoordinatorLayout
類似于一個FrameLayout 的容器,在嵌套滑動中有兩個功能:
1.作為嵌套滑動頂層布局
2.作為與一個或者多個直接子view進(jìn)行交互的特定容器
通過給 CoordinatorLayout 的直接子view設(shè)置 Behaviors 屬性猿涨,實(shí)現(xiàn)子view之間進(jìn)行不同的滑動交互以及布局修改姆怪。實(shí)現(xiàn)子view之間執(zhí)行移動或者動畫的澡绩,實(shí)現(xiàn)其他子View跟隨動作俺附。
Behavior
這個CoordinatorLayout類內(nèi)部的 抽象類,定義了子試圖的交互行為召调。這些互動可能包括拖曳蛮浑,滑動,投擲艺沼,或任何其他手勢蕴掏。主要的Api如下:
CoordinatorLayout.Behavior
/**
* 是否給應(yīng)用了Behavior的View,指定一個觀察的布局
* 當(dāng)布局發(fā)生變化的時候
* 確定所提供的子視圖是否有另一個特定的同級視圖作為布局依賴項(xiàng)。
* 注意:本身的View會重新布局
*
* @param parent 頂層嵌套布局
* @param child 綁定behavior的View(觀察者,就是TextView本身)
* @param dependency 被觀察的view(被觀察者挽荡,就是同級別的其他子視圖)
* @return 這里可以檢查自己需要觀察的試圖即供,是返回true,否則返回false
*/
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
Log.i(TAG,"layoutDependsOn child " + child.getClass().getSimpleName()
+ " dependency " + dependency.getClass().getSimpleName());
// 這里檢查被觀察者(TexView觀察的是滑動NestedScrollView)
return dependency instanceof NestedScrollView;
}
/**
* 是否響應(yīng)子程序依賴視圖(被觀察者)中的更改
* 每當(dāng)依賴視圖在標(biāo)準(zhǔn)布局流之外的大小或位置發(fā)生變化時青自,都會調(diào)用此方法
*
* @param parent 頂層嵌套布局
* @param child 綁定behavior的View(觀察者,就是TextView本身)
* @param dependency 被觀察的view(被觀察者驱证,就是同級別的其他子視圖)
* @return true 響應(yīng)了被觀察者的變化,false沒有響應(yīng)
*/
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
Log.i(TAG,"onDependentViewChanged child " + child.getClass().getSimpleName()
+ " dependency " + dependency.getClass().getSimpleName());
//一開始 等于0
if (deltaY == 0) {
//初始化兩者之間的距離
deltaY = dependency.getY() - child.getHeight();
}
Log.i("DN deltaY------------>",deltaY+"------------");
//被觀察者View的Y坐標(biāo) - 觀察者的高度 得到兩者之間剩余的距離
float dy = dependency.getY() - child.getHeight();
//如果距離小于0 就賦值0 如果距離大于等于0 就把剩余距離賦值給它
dy = dy < 0 ? 0 : dy;
//計(jì)算Y軸每次偏移的距離
float y = -(dy / deltaY) * child.getHeight();
Log.i("DN-------------->",y+"------------");
//設(shè)置Y軸的偏移參數(shù)
child.setTranslationY(y);
return false;
}
/**
* 當(dāng)coordinatorLayout 的子View試圖開始嵌套滑動的時候被調(diào)用
* 任何與協(xié)調(diào)員Layout的任何直接子級相關(guān)聯(lián)的行為都可能響應(yīng)此事件并返回TRUE,
* 以指示協(xié)調(diào)員Layout應(yīng)該充當(dāng)此滾動條的嵌套滾動父級伙单。
* 只有從此方法返回true的行為才會接收后續(xù)嵌套滾動事件车份。
*
* @param coordinatorLayout 頂層嵌套布局
* @param child 綁定behavior的View(觀察者,就是TextView本身)
* @param directTargetChild 該子視圖是或包含嵌套滾動操作的目標(biāo)
* @param target View啟動嵌套滾動的協(xié)調(diào)員Layout的后代視圖
* @param nestedScrollAxes 嵌套滑動滑動方向,橫向或者豎向
* @param type 導(dǎo)致此滾動事件的輸入類型
* @return 如果行為希望接受此嵌套滾動扫沼,則為true。
*/
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild,
View target, int nestedScrollAxes, int type) {
Log.i(TAG,"onStartNestedScroll type " + type);
return true;
}
/**
* 當(dāng)正在進(jìn)行的嵌套滾動即將更新時严就,在目標(biāo)消耗任何滾動距離之前調(diào)用
* 在nested scroll child 消費(fèi)掉自己的滾動距離之前梢为,嵌套滾動每次被nested scroll child
* 更新都會調(diào)用onNestedPreScroll。注意有個重要的參數(shù)consumed铸董,可以修改這個數(shù)組表示你消費(fèi)
* 了多少距離粟害。假設(shè)用戶滑動了100px,child 做了90px 的位移,你需要把 consumed[1]的值改成90悲幅,
* 這樣coordinatorLayout就能知道只處理剩下的10px的滾動。
*
* @param coordinatorLayout 頂層嵌套布局
* @param child 綁定behavior的View(觀察者,就是TextView本身)
* @param target View啟動嵌套滾動的協(xié)調(diào)員Layout的后代視圖
* @param dx 用戶試圖滾動的原始水平像素?cái)?shù)
* @param dy 用戶試圖滾動的原始垂直像素?cái)?shù)
* @param consumed 輸出參數(shù)卓鹿。消費(fèi)[0]應(yīng)設(shè)置為消耗的dx的距離留荔,消費(fèi)[1]應(yīng)設(shè)置為所消費(fèi)的dy的距離存谎。
*/
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed, int type) {
Log.i(TAG,"onNestedPreScroll dx " + dx
+ " dy " + dy);
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed,type);
}
/**
* 當(dāng)正在進(jìn)行的嵌套滾動更新并且目標(biāo)已滾動或試圖滾動時調(diào)用肥隆。
*
* @param coordinatorLayout 頂層嵌套布局
* @param child 綁定behavior的View
* @param target 被觀察的view(被觀察者,就是同級別的其他子視圖)
* @param dxConsumed target 已經(jīng)消費(fèi)的x方向的距離
* @param dyConsumed target 已經(jīng)消費(fèi)的y方向的距離
* @param dxUnconsumed x 方向剩下的滾動距離
* @param dyUnconsumed y 方向剩下的滾動距離
*/
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed,
int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
Log.i(TAG,"onNestedScroll child " + child.getClass().getSimpleName()
+ " dependency " + target.getClass().getSimpleName());
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,type);
}
/**
* 嵌套滾動結(jié)束時被調(diào)用恰聘,這是一個清除滾動狀態(tài)等的好時機(jī)晴叨。
*
* @param coordinatorLayout 頂層嵌套布局
* @param child 綁定behavior的View(觀察者,就是TextView本身)
* @param target 被觀察的view(被觀察者矾屯,就是同級別的其他子視圖)
*/
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int type) {
Log.i(TAG,"onStopNestedScroll child " + child.getClass().getSimpleName()
+ " dependency " + target.getClass().getSimpleName());
super.onStopNestedScroll(coordinatorLayout, child, target,type);
}
/**
* onStartNestedScroll返回true才會觸發(fā)這個方法,接受滾動處理后回調(diào)孙技,可以在這個
* 方法里做一些準(zhǔn)備工作,如一些狀態(tài)的重置等牵啦。
*
* @param coordinatorLayout 頂層嵌套布局
* @param child 綁定behavior的View(觀察者,就是TextView本身)
* @param directTargetChild 該子視圖是或包含嵌套滾動操作的目標(biāo)
* @param target 被觀察的view(被觀察者,就是同級別的其他子視圖)
* @param nestedScrollAxes 方向
* @param type 導(dǎo)致此滾動事件的輸入類型
*/
@Override
public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, View child, View directTargetChild,
View target, int nestedScrollAxes,int type) {
Log.i(TAG,"onNestedScrollAccepted child " + child.getClass().getSimpleName()
+ " dependency " + target.getClass().getSimpleName());
super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes,type);
}
/**
* 用戶松開手指并且會發(fā)生慣性動作之前調(diào)用楞件,參數(shù)提供了速度信息土浸,可以根據(jù)這些速度信息
* 決定最終狀態(tài)盹愚,比如滾動Header,是讓Header處于展開狀態(tài)還是折疊狀態(tài)皆怕。返回true 表
* 示消費(fèi)了fling.
*
* @param coordinatorLayout 頂層嵌套布局
* @param child 綁定behavior的View(觀察者,就是TextView本身)
* @param target 被觀察的view(被觀察者愈腾,就是同級別的其他子視圖)
* @param velocityX x 方向的速度
* @param velocityY y 方向的速度
* @return true 行為消耗了,否則沒有
*/
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target,
float velocityX, float velocityY) {
Log.i(TAG,"onNestedPreFling child " + child.getClass().getSimpleName()
+ " dependency " + target.getClass().getSimpleName());
return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
}
//可以重寫這個方法對子View 進(jìn)行重新布局
@Override
public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
Log.i(TAG,"onLayoutChild child " + child.getClass().getSimpleName());
return super.onLayoutChild(parent, child, layoutDirection);
}
上面的代碼用也用 TextView作為觀察者悦即,自定義它的Behavior的行為橱乱,跟隨 NestedScrollView 滑動
https://github.com/liuguangsen/HightUi/blob/master/app/src/main/java/com/liugs/materialdesigntest/behavior/BehaviorTest.java