MD控制元件之自定義behavior
阿新 • • 發佈:2019-01-05
首先這裡介紹系統自帶的behavior中的一些方法
/**
* 表示是否給應用了Behavior 的View 指定一個依賴的佈局,通常,當依賴的View 佈局發生變化時
* 不管被被依賴View 的順序怎樣,被依賴的View也會重新佈局
* @param parent
* @param child 繫結behavior 的View
* @param dependency 依賴的view
* @return 如果child 是依賴的指定的View 返回true,否則返回false
*/
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return super.layoutDependsOn(parent, child, dependency);
}
/**
* 當被依賴的View 狀態(如:位置、大小)發生變化時,這個方法被呼叫
* @param parent
* @param child
* @param dependency
* @return
*/
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
return super.onDependentViewChanged(parent, child, dependency);
}
/**
* 當coordinatorLayout 的子View試圖開始巢狀滑動的時候被呼叫。當返回值為true的時候表明
* coordinatorLayout 充當nested scroll parent 處理這次滑動,需要注意的是隻有當返回值為true
* 的時候,Behavior 才能收到後面的一些nested scroll 事件回撥(如:onNestedPreScroll、onNestedScroll等)
* 這個方法有個重要的引數nestedScrollAxes,表明處理的滑動的方向。
*
* @param coordinatorLayout 和Behavior 繫結的View的父CoordinatorLayout
* @param child 和Behavior 繫結的View
* @param directTargetChild
* @param target
* @param nestedScrollAxes 巢狀滑動 應用的滑動方向,看 {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
* {@link ViewCompat#SCROLL_AXIS_VERTICAL}
* @return
*/
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
/**
* 巢狀滾動發生之前被呼叫
* 在nested scroll child 消費掉自己的滾動距離之前,巢狀滾動每次被nested scroll child
* 更新都會呼叫onNestedPreScroll。注意有個重要的引數consumed,可以修改這個陣列表示你消費
* 了多少距離。假設使用者滑動了100px,child 做了90px 的位移,你需要把 consumed[1]的值改成90,
* 這樣coordinatorLayout就能知道只處理剩下的10px的滾動。
* @param coordinatorLayout
* @param child
* @param target
* @param dx 使用者水平方向的滾動距離
* @param dy 使用者豎直方向的滾動距離
* @param consumed
*/
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
}
/**
* 進行巢狀滾動時被呼叫
* @param coordinatorLayout
* @param child
* @param target
* @param dxConsumed target 已經消費的x方向的距離
* @param dyConsumed target 已經消費的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) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
/**
* 巢狀滾動結束時被呼叫,這是一個清除滾動狀態等的好時機。
* @param coordinatorLayout
* @param child
* @param target
*/
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {
super.onStopNestedScroll(coordinatorLayout, child, target);
}
/**
* onStartNestedScroll返回true才會觸發這個方法,接受滾動處理後回撥,可以在這個
* 方法裡做一些準備工作,如一些狀態的重置等。
* @param coordinatorLayout
* @param child
* @param directTargetChild
* @param target
* @param nestedScrollAxes
*/
@Override
public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
/**
* 使用者鬆開手指並且會發生慣性動作之前呼叫,引數提供了速度資訊,可以根據這些速度資訊
* 決定最終狀態,比如滾動Header,是讓Header處於展開狀態還是摺疊狀態。返回true 表
* 示消費了fling.
*
* @param coordinatorLayout
* @param child
* @param target
* @param velocityX x 方向的速度
* @param velocityY y 方向的速度
* @return
*/
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY) {
return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
}
/**
* 擺放子 View 的時候呼叫,可以重寫這個方法對子View 進行重新佈局
*/
@Override
public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
return super.onLayoutChild(parent, child, layoutDirection);
}
自定義一個behavior
public class TanslationBehavior extends FloatingActionButton.Behavior {
// 關注垂直滾動 ,而且向上的時候是出來,向下是隱藏
public TanslationBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
//新增一個標誌位
private boolean isOut = false;
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0) {//大於0代表向上滑動,隱藏
if (!isOut) {
// 往上滑動,是隱藏 , 加一個標誌位 已經往下走了
//獲取控制元件距離底部的距離+控制元件的高度
int translationY = ((CoordinatorLayout.LayoutParams) child.getLayoutParams()).bottomMargin
+ child.getMeasuredHeight();
child.animate().translationY(translationY).setDuration(500).start();
isOut = true;
}
} else {//向下滑動
if (isOut) {
child.animate().translationY(0).setDuration(500).start();
isOut = false;
}
}
}
}
主佈局
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/tool_bar"
app:title="知乎首頁"
app:titleTextColor="#FFFFFF"
app:layout_scrollFlags="scroll|enterAlways"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="70dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:src="@mipmap/ic_launcher"
app:layout_behavior="com.hbwj.a13_behavior.TanslationBehavior"
app:layout_scrollFlags="scroll|enterAlways|snap" />
<LinearLayout
android:id="@+id/bottom_tab_layout"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_alignParentBottom="true"
android:background="@android:color/white"
app:layout_behavior="@string/bottom_sheet_behavior">
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="@mipmap/ic_launcher" />
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="@mipmap/ic_launcher"
/>
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:src="@mipmap/ic_launcher"
android:layout_weight="1"/>
<ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:src="@mipmap/ic_launcher"
android:layout_weight="1" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
MainActivity中的主要程式碼
//不能少,否則比如像微信一樣加選單項時無法加入
Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
// 監聽 ScrollView 的滾動 等等一些處理
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new RecyclerView.Adapter() {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_behavior,parent,false);
// View itemView = View.inflate(BehaviorActivity.this,R.layout.item_behavior,null);
ViewHolder viewHolder = new ViewHolder(itemView);
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 100;
}
});
}
private class ViewHolder extends RecyclerView.ViewHolder{
public ViewHolder(View itemView) {
super(itemView);
}
}