Android CoordinatorLayout高級(jí)用法之自定義Behavior
上次簡(jiǎn)單的說了一下CoordinatorLayout的基本用法(android特性之CoordinatorLayout用法探析實(shí)例)。其中CoordinatorLayout給我們提供了一種新的事件的處理方式,Behavior。還記得那一串字符串嗎?
app:layout_behavior="@string/appbar_scrolling_view_behavior"
其實(shí)它并不是一個(gè)字符串資源,而它代表的是一個(gè)類,就是一個(gè)Behavior,這玩意其實(shí)還可以自定義的。
首先,來讓我見識(shí)一下它的真面目:
public static abstract class Behavior<V extends View> {
...
}
Behavior是CoordinatorLayout的一個(gè)內(nèi)部泛型抽象類。內(nèi)部類中指定的view類型規(guī)定了哪種類型的view的可以使用才Behavior。因此,如果沒有特殊需求,直接指定view為View就行了。
1.某個(gè)view需要根據(jù)監(jiān)聽另一個(gè)的行為來控制自己的行為,這個(gè)時(shí)候我們需要重寫2個(gè)方法:
public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {
return false;
}
public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) {
return false;
}
2.我們的view需要根據(jù)監(jiān)聽CoordinatorLayout中的子view的滾動(dòng)行為來改變自己的狀態(tài),現(xiàn)在我們就需要重寫下面的方法了:
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,讓一個(gè)view跟隨另一個(gè)view的行為而實(shí)現(xiàn)狀態(tài)的改變。我們定義一個(gè)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;
}
}
我們?cè)谧远x的Behavior中,帶有參數(shù)的這個(gè)構(gòu)造必須要重載,因?yàn)樵贑oordinatorLayout里利用反射去獲取這個(gè)Behavior的時(shí)候就是拿的這個(gè)構(gòu)造。
在layoutDependsOn中,我們?cè)O(shè)置讓View的狀態(tài)來跟隨AppBarLayout,也就是說只有AppBarLayout的狀態(tài)發(fā)生變化才會(huì)影響到View。
接下來就是在onDependentViewChanged中對(duì)View做出相應(yīng)的狀態(tài)改變。在代碼中,我們做的改變是,跟隨dependedcy一起在Y軸方向移動(dòng),來達(dá)到顯示和隱藏的目的。先布局如下:
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中我們?cè)O(shè)置了
app:layout_behavior="com.lingyun.coordinatorlayoutdemo.FooterBehavior"
這正好就是我們自定義的FooterBehavior的絕對(duì)路徑。下面我們來看一下效果圖:

在效果圖上我們看到,當(dāng)我們上下滑動(dòng)屏幕的時(shí)候,底部footer布局和標(biāo)題Toolbar一起移動(dòng),實(shí)現(xiàn)了顯示和隱藏的效果。
學(xué)會(huì)了第一張簡(jiǎn)單的自定義Behavior之后,接下來我們?cè)賮砜匆幌碌诙N情況,滑動(dòng)。因?yàn)檫@個(gè)是根據(jù)CoordinatorLayout里子view的滾動(dòng)行為來改變我們的狀態(tài)的,所以情況1中的2個(gè)方法我們就不需要重寫了。下面,我們用情況2來實(shí)現(xiàn)上面的效果。
先來看一下下面幾個(gè)參數(shù):
child:簡(jiǎn)單點(diǎn)說,就是用到當(dāng)前CoordinatorLayout的子View,響應(yīng)此Behavior。
target:CoordinatorLayout的子View,引起滾動(dòng)的view,其實(shí)child的狀態(tài)改變是根據(jù)target來實(shí)現(xiàn)的。
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軸上滾動(dòng)。
方法onNestPreScroll中,就是時(shí)時(shí)根據(jù)target距離屏幕頂端的距離計(jì)算出滾動(dòng)的距離,然后根據(jù)比例計(jì)算出child移動(dòng)的距離。
截圖和上面比較沒啥區(qū)別:

基本的自定義Behavior就是這樣了,以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android UI設(shè)計(jì)與開發(fā)之實(shí)現(xiàn)應(yīng)用程序只啟動(dòng)一次引導(dǎo)界面
這篇文章主要為大家詳細(xì)介紹了Android UI設(shè)計(jì)與開發(fā)之實(shí)現(xiàn)應(yīng)用程序只啟動(dòng)一次引導(dǎo)界面,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
Android開發(fā)筆記之:返回鍵的復(fù)寫onBackPressed()介紹
本篇文章是對(duì)Android中返回鍵的復(fù)寫onBackPressed()進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Android控件FlowLikeView實(shí)現(xiàn)點(diǎn)贊動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了一個(gè)點(diǎn)贊動(dòng)畫的優(yōu)雅控件FlowLikeView,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
Android實(shí)現(xiàn)衛(wèi)星菜單效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)衛(wèi)星菜單效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
Kotlin基礎(chǔ)學(xué)習(xí)之Deprecated與Suppress注解使用
這篇文章主要給大家介紹了關(guān)于Kotlin基礎(chǔ)學(xué)習(xí)之Deprecated與Suppress注解使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Kotlin具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
如何在Android Studio下進(jìn)行NDK開發(fā)
這篇文章主要介紹了如何在Android Studio下進(jìn)行NDK開發(fā),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05

