Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> CoordinatorLayout用法學習

CoordinatorLayout用法學習

編輯:關於Android編程

以前我們創建項目時候,一個頁面的布局是線性或者相對等,當我在AS上新建一個module時,系統默認的最外層布局不再是我們熟悉的五大布局中的一種,而是一個全新的布局:CoordinatorLayout。它是Material風格的重要組件, 作為布局的頂層控件,協調(Coordinate)其他組件, 實現聯動。

activity_main.xml主布局




    

        

    

    

    

content_main.xml




    

看看效果圖如下:
這裡寫圖片描述

??很明顯,狀態欄是有問題的,我們只需要將主布局的
android:fitsSystemWindows=”true”取調即可
以下是去掉之後的顯示狀態
這裡寫圖片描述

這裡寫圖片描述

以上的布局需要注意幾個點:
app:layout_scrollFlags=”scroll"enterAlways”
app:layout_behavior=”@string/appbar_scrolling_view_behavior”

其中控制ToolBar是否可以滾出屏幕的屬性是由app:layout_scrollFlags=”scroll|enterAlways”

enterAlwaysCollapsed: 顧名思義,這個flag定義的是何時進入(已經消失之後何時再次顯示)。假設你定義了一個最小高度(minHeight)同時enterAlways也定義了,那麼view將在到達這個最小高度的時候開始顯示,並且從這個時候開始慢慢展開,當滾動到頂部的時候展開完。

exitUntilCollapsed: 同樣顧名思義,這個flag時定義何時退出,當你定義了一個minHeight,這個view將在滾動到達這個最小高度的時候消失

我們來了解下,如何自定義Behavior
CoordinatorLayout的工作原理是搜索定義了CoordinatorLayout Behavior 的子view,不管是通過在xml中使用app:layout_behavior標簽還是通過在代碼中對view類使用@DefaultBehavior修飾符來添加注解。當滾動發生的時候,CoordinatorLayout會嘗試觸發那些聲明了依賴的子view。要自己定義CoordinatorLayout Behavior,你需要實現layoutDependsOn() 和onDependentViewChanged()兩個方法。

android.support.design.widget.AppBarLayout$ScrollingViewBehavior

其實它並不是一個字符串資源,而它代表的是一個類

public static class ScrollingViewBehavior extends ViewOffsetBehavior

class ViewOffsetBehavior extends Behavior

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;  
       } 

結合我們一個列子來理理思路,首先看例子的效果圖:
這裡寫圖片描述

先看這個例子的主布局activity_main.xml




    

        

    

    

    

上面的主布局中,我們為FloatingActionButton增加了一個自定義的屬性行為

 app:layout_behavior="com.example.administrator.myapplication.FooterBehavior"

意思就是:這個FloatingActionButton根據監聽AppBarLayout滑動的行為來控制自己的行為

content_main.xml




    

FooterBehavior

package com.example.administrator.myapplication;

import android.content.Context;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.View;

public class FooterBehavior extends CoordinatorLayout.Behavior{

    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;  
    }  
}  

這兩個方法的參數都是一樣的,解釋一下,第一個不用說,就是當前的CoordinatorLayout,第二個參數是我們設置這個Behavior的View,也就是FloatingActionButton, 第三個是我們關心的那個View。如何知道關心的哪個呢?layoutDependsOn的返回值決定了一切!

我們的例子layoutDependsOn方法中,return dependency instanceof AppBarLayout;是關心的AppBarLayout,也就是Toolbar(AppBarLayout)變化位置,引起FloatingActionButton的位置變化

onDependentViewChanged方法意思是什麼呢?
先計算出Toolbar(AppBarLayout)暴露在屏幕的比例大小
然後計算出FloatingActionButton需要移動到的位置

以下是log日志

 Log.i("TAG","scaleY-->>"+scaleY+",,child.getHeight() * scaleY-->>"+child.getHeight() * scaleY);
 I/TAG: scaleY-->>0.05952381,,child.getHeight() * scaleY-->>8.928572
I/TAG: scaleY-->>0.31547618,,child.getHeight() * scaleY-->>47.321426
I/TAG: scaleY-->>0.8214286,,child.getHeight() * scaleY-->>123.21429
 I/TAG: scaleY-->>1.0,,child.getHeight() * scaleY-->>150.0
 I/TAG: scaleY-->>0.875,,child.getHeight() * scaleY-->>131.25
 I/TAG: scaleY-->>0.10119048,,child.getHeight() * scaleY-->>15.178572
 I/TAG: scaleY-->>0.0,,child.getHeight() * scaleY-->>0.0

2、第二種情況,滑動。因為這個是根據CoordinatorLayout裡子view的滾動行為來改變我們的狀態的,所以情況1中的2個方法我們就不需要重寫了。下面,我們用情況2來實現上面的效果。

package com.example.administrator.myapplication;

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.View;

public class FooterBehavior extends CoordinatorLayout.Behavior{

    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移動的距離。

我們簡單看下源碼

 * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
         *                          associated with
         * @param child the child view of the CoordinatorLayout this Behavior is associated with
         * @param directTargetChild the child view of the CoordinatorLayout that either is or
         *                          contains the target of the nested scroll operation
         * @param target the descendant view of the CoordinatorLayout initiating the nested scroll
         * @param nestedScrollAxes the axes that this nested scroll applies to. See
         *                         {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
         *                         {@link ViewCompat#SCROLL_AXIS_VERTICAL}
         * @return true if the Behavior wishes to accept this nested scroll
         *
         * @see NestedScrollingParent#onStartNestedScroll(View, View, int)
         */
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
                V child, View directTargetChild, View target, int nestedScrollAxes) {
            return false;
        }

百度翻譯如下:
child:coordinatorlayout孩子的這種行為是與(本例就是FloatingActionButton)
target :啟動嵌套滾動coordinatorlayout後裔的觀點(本例就是AppBarLayout)
directTargetChild 這個涉及到深層次的布局問題,我們的布局中只有一個控件FloatingActionButton

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved