溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android CoordinatorLayout高級用法之自定義Behavior

發(fā)布時間:2020-10-22 02:04:52 來源:腳本之家 閱讀:258 作者:FightSeeker 欄目:移動開發(fā)

上次簡單的說了一下CoordinatorLayout的基本用法(android特性之CoordinatorLayout用法探析實例)。其中CoordinatorLayout給我們提供了一種新的事件的處理方式,Behavior。還記得那一串字符串嗎?

app:layout_behavior="@string/appbar_scrolling_view_behavior" 

其實它并不是一個字符串資源,而它代表的是一個類,就是一個Behavior,這玩意其實還可以自定義的。

首先,來讓我見識一下它的真面目:

public static abstract class Behavior<V extends View> { 
... 
} 

Behavior是CoordinatorLayout的一個內(nèi)部泛型抽象類。內(nèi)部類中指定的view類型規(guī)定了哪種類型的view的可以使用才Behavior。因此,如果沒有特殊需求,直接指定view為View就行了。

1.某個view需要根據(jù)監(jiān)聽另一個的行為來控制自己的行為,這個時候我們需要重寫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需要根據(jù)監(jiān)聽CoordinatorLayout中的子view的滾動行為來改變自己的狀態(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,讓一個view跟隨另一個view的行為而實現(xiàn)狀態(tài)的改變。我們定義一個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中,帶有參數(shù)的這個構(gòu)造必須要重載,因為在CoordinatorLayout里利用反射去獲取這個Behavior的時候就是拿的這個構(gòu)造。

在layoutDependsOn中,我們設置讓View的狀態(tài)來跟隨AppBarLayout,也就是說只有AppBarLayout的狀態(tài)發(fā)生變化才會影響到View。

接下來就是在onDependentViewChanged中對View做出相應的狀態(tài)改變。在代碼中,我們做的改變是,跟隨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的絕對路徑。下面我們來看一下效果圖:

Android CoordinatorLayout高級用法之自定義Behavior

在效果圖上我們看到,當我們上下滑動屏幕的時候,底部footer布局和標題Toolbar一起移動,實現(xiàn)了顯示和隱藏的效果。

學會了第一張簡單的自定義Behavior之后,接下來我們再來看一下第二種情況,滑動。因為這個是根據(jù)CoordinatorLayout里子view的滾動行為來改變我們的狀態(tài)的,所以情況1中的2個方法我們就不需要重寫了。下面,我們用情況2來實現(xiàn)上面的效果。
先來看一下下面幾個參數(shù):

child:簡單點說,就是用到當前CoordinatorLayout的子View,響應此Behavior。

target:CoordinatorLayout的子View,引起滾動的view,其實child的狀態(tài)改變是根據(jù)target來實現(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軸上滾動。
方法onNestPreScroll中,就是時時根據(jù)target距離屏幕頂端的距離計算出滾動的距離,然后根據(jù)比例計算出child移動的距離。
截圖和上面比較沒啥區(qū)別:

Android CoordinatorLayout高級用法之自定義Behavior

基本的自定義Behavior就是這樣了,以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI