您好,登錄后才能下訂單哦!
上次簡單的說了一下CoordinatorLayout的基本用法(android特性之CoordinatorLayout用法探析實例)。其中CoordinatorLayout給我們提供了一種新的事件的處理方式,Behavior。還記得那一串字符串嗎?
app:layout_behavior="@string/appbar_scrolling_view_behavior"
其實它并不是一個字符串資源,而它代表的是一個類,就是一個Behavior,這玩意其實還可以自定義的。
首先,來讓我見識一下它的真面目:
public static abstract class Behavior<V extends View> { ... }
Behavior是CoordinatorLayout的一個內部泛型抽象類。內部類中指定的view類型規定了哪種類型的view的可以使用才Behavior。因此,如果沒有特殊需求,直接指定view為View就行了。
1.某個view需要根據監聽另一個的行為來控制自己的行為,這個時候我們需要重寫2個方法:
public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) { return false; }
public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) { return false; }
2.我們的view需要根據監聽CoordinatorLayout中的子view的滾動行為來改變自己的狀態,現在我們就需要重寫下面的方法了:
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) { return false; }
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) { // Do nothing }
下面我們先來看一下情況1,讓一個view跟隨另一個view的行為而實現狀態的改變。我們定義一個Behavior,名字叫:FooterBehavior,代碼如下:
package com.lingyun.coordinatorlayoutdemo; import android.content.Context; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CoordinatorLayout; import android.util.AttributeSet; import android.view.View; /** * Created by dandy on 2016/7/4. */ public class FooterBehavior extends CoordinatorLayout.Behavior<View>{ public FooterBehavior(Context context,AttributeSet attributeSet){ super(context,attributeSet); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return dependency instanceof AppBarLayout; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { float scaleY = Math.abs(dependency.getY()) / dependency.getHeight(); child.setTranslationY(child.getHeight() * scaleY); return true; } }
我們在自定義的Behavior中,帶有參數的這個構造必須要重載,因為在CoordinatorLayout里利用反射去獲取這個Behavior的時候就是拿的這個構造。
在layoutDependsOn中,我們設置讓View的狀態來跟隨AppBarLayout,也就是說只有AppBarLayout的狀態發生變化才會影響到View。
接下來就是在onDependentViewChanged中對View做出相應的狀態改變。在代碼中,我們做的改變是,跟隨dependedcy一起在Y軸方向移動,來達到顯示和隱藏的目的。先布局如下:
activity_main.xml布局:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <include layout="@layout/appbar_main"/> <include layout="@layout/content_main" /> <include layout="@layout/footer_main"/> </android.support.design.widget.CoordinatorLayout>
appbar_main.xml布局如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways"/> </android.support.design.widget.AppBarLayout>
content_main.xml布局如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="你是誰?你從哪里來?你到哪里去?"/> </android.support.v4.widget.NestedScrollView>
footer_main.xml布局如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="60dp" android:layout_gravity="bottom" android:background="?attr/colorPrimary" app:layout_behavior="com.lingyun.coordinatorlayoutdemo.FooterBehavior"> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:text="Tab1" android:layout_weight="1" android:gravity="center" android:textColor="@android:color/white"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:text="Tab2" android:layout_weight="1" android:gravity="center" android:textColor="@android:color/white"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:text="Tab3" android:layout_weight="1" android:gravity="center" android:textColor="@android:color/white"/> </LinearLayout>
注意看,在footer_main.xml中我們設置了
app:layout_behavior="com.lingyun.coordinatorlayoutdemo.FooterBehavior"
這正好就是我們自定義的FooterBehavior的絕對路徑。下面我們來看一下效果圖:
在效果圖上我們看到,當我們上下滑動屏幕的時候,底部footer布局和標題Toolbar一起移動,實現了顯示和隱藏的效果。
學會了第一張簡單的自定義Behavior之后,接下來我們再來看一下第二種情況,滑動。因為這個是根據CoordinatorLayout里子view的滾動行為來改變我們的狀態的,所以情況1中的2個方法我們就不需要重寫了。下面,我們用情況2來實現上面的效果。
先來看一下下面幾個參數:
child:簡單點說,就是用到當前CoordinatorLayout的子View,響應此Behavior。
target:CoordinatorLayout的子View,引起滾動的view,其實child的狀態改變是根據target來實現的。
package com.lingyun.coordinatorlayoutdemo; import android.content.Context; import android.support.design.widget.CoordinatorLayout; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.View; /** * Created by dandy on 2016/7/4. */ public class FooterBehavior extends CoordinatorLayout.Behavior<View>{ private float targetY = -1; private static final String TAG = "FooterBehavior"; public FooterBehavior(Context context,AttributeSet attributeSet){ super(context, attributeSet); } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { if(targetY == -1){ targetY = target.getY(); } return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); float scrooY = targetY - Math.abs(target.getY()); float scaleY = scrooY / targetY; child.setTranslationY(child.getHeight() * scaleY); } }
在方法onStartNestedScroll中,首先獲取target在Y軸上距離屏幕頂端的距離,然后判斷是否是在Y軸上滾動。
方法onNestPreScroll中,就是時時根據target距離屏幕頂端的距離計算出滾動的距離,然后根據比例計算出child移動的距離。
截圖和上面比較沒啥區別:
基本的自定義Behavior就是這樣了,以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。