英文原文:https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout html
這篇文章專門講解和CoordinatorLayout相關的知識點,這也是Design Support Library中最重要與最難的部分。java
CoordinatorLayout 實現了多種Material Design中提到的滾動效果。目前這個框架提供了幾種不用寫動畫代碼就能工做的方法,這些效果包括:android
讓浮動操做按鈕上下滑動,爲Snackbar留出空間。api
擴展或者縮小Toolbar或者頭部,讓主內容區域有更多的空間。app
控制哪一個view應該擴展仍是收縮,以及其顯示大小比例,包括視差滾動效果動畫。框架
首先確保遵循了Design Support Library的使用說明。ide
CoordinatorLayout能夠用來配合浮動操做按鈕的 layout_anchor 和 layout_gravity屬性創造出浮動效果,詳情請參見浮動操做按鈕指南。佈局
當Snackbar在顯示的時候,每每出如今屏幕的底部。爲了給Snackbar留出空間,浮動操做按鈕須要向上移動。動畫
只要使用CoordinatorLayout做爲基本佈局,將自動產生向上移動的動畫。浮動操做按鈕有一個 默認的 behavior來檢測Snackbar的添加並讓按鈕在Snackbar之上呈現上移與Snackbar等高的動畫。ui
<android.support.design.widget.CoordinatorLayout android:id="@+id/main_content" 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"> <android.support.v7.widget.RecyclerView android:id="@+id/rvToDoList" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> <android.support.design.widget.FloatingActionButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:layout_margin="16dp" android:src="@mipmap/ic_launcher" app:layout_anchor="@id/rvToDoList" app:layout_anchorGravity="bottom|right|end"/> </android.support.design.widget.CoordinatorLayout>
首先須要確保你不是使用已通過時的ActionBar。務必遵循 使用ToolBar做爲actionbar這篇文章的指南。一樣,這裏也須要CoordinatorLayout做爲主佈局容器。
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <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.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="@dimen/detail_backdrop_height" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:fitsSystemWindows="true"> <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.support.design.widget.AppBarLayout>
而後,咱們須要定義AppBarLayout與滾動視圖之間的聯繫。在RecyclerView或者任意支持嵌套滾動的view好比NestedScrollView上添加app:layout_behavior。support library包含了一個特殊的字符串資源@string/appbar_scrolling_view_behavior,它和AppBarLayout.ScrollingViewBehavior相匹配,用來通知AppBarLayout 這個特殊的view什麼時候發生了滾動事件,這個behavior須要設置在觸發事件(滾動)的view之上。注意:根據官方的谷歌文檔,AppBarLayout目前必須是第一個嵌套在CoordinatorLayout裏面的子view。
<android.support.v7.widget.RecyclerView android:id="@+id/rvToDoList" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior">
AppBarLayout裏面定義的view只要設置了app:layout_scrollFlags屬性,就能夠在RecyclerView滾動事件發生的時候被觸發:當CoordinatorLayout發現RecyclerView中定義了這個屬性,它會搜索本身所包含的其餘view,看看是否有view與這個behavior相關聯。AppBarLayout.ScrollingViewBehavior描述了RecyclerView與AppBarLayout之間的依賴關係。RecyclerView的任意滾動事件都將觸發AppBarLayout或者AppBarLayout裏面view的改變。
<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" 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:layout_scrollFlags="scroll|enterAlways"/> </android.support.design.widget.AppBarLayout>enterAlways: 一旦向上滾動這個view就可見。app:layout_scrollFlags屬性裏面必須至少啓用scroll這個flag,這樣這個view纔會滾動出屏幕,不然它將一直固定在頂部。可使用的其餘flag有:
enterAlwaysCollapsed: 顧名思義,這個flag定義的是什麼時候進入(已經消失以後什麼時候再次顯示)。假設你定義了一個最小高度(minHeight)同時enterAlways也定義了,那麼view將在到達這個最小高度的時候開始顯示,而且從這個時候開始慢慢展開,當滾動到頂部的時候展開完。
exitUntilCollapsed: 一樣顧名思義,這個flag時定義什麼時候退出,當你定義了一個minHeight,這個view將在滾動到達這個最小高度的時候消失。
記住,要把帶有scroll flag的view放在前面,這樣收回的view才能讓正常退出,而固定的view繼續留在頂部。
此時,你應該注意到咱們的Toolbar可以響應滾動事件了。
若是想製造toolbar的摺疊效果,咱們必須把Toolbar放在CollapsingToolbarLayout中:
<android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginEnd="64dp" app:expandedTitleMarginStart="48dp" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways"></android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout>
如今效果就成了:
一般,咱們咱們都是設置Toolbar的title,而如今,咱們須要把title設置在CollapsingToolBarLayout上,而不是Toolbar。
CollapsingToolbarLayout collapsingToolbar =(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); collapsingToolbar.setTitle("Title");
CollapsingToolbarLayout還能讓咱們作出更高級的動畫,好比在裏面放一個ImageView,而後在它摺疊的時候漸漸淡出。同時在用戶滾動的時候title的高度也會隨着改變。
爲了製造出這種效果,咱們添加一個定義了app:layout_collapseMode="parallax" 屬性的ImageView。
<android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginEnd="64dp" app:expandedTitleMarginStart="48dp" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_scrollFlags="scroll|enterAlways"></android.support.v7.widget.Toolbar> <ImageView android:src="@drawable/cheese_1" app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="centerCrop" app:layout_collapseMode="parallax" android:minHeight="100dp"/> </android.support.design.widget.CollapsingToolbarLayout>
CoordinatorLayout的工做原理是搜索定義了CoordinatorLayout Behavior 的子view,無論是經過在xml中使用app:layout_behavior標籤仍是經過在代碼中對view類使用@DefaultBehavior修飾符來添加註解。當滾動發生的時候,CoordinatorLayout會嘗試觸發那些聲明瞭依賴的子view。
要本身定義CoordinatorLayout Behavior,你須要實現layoutDependsOn() 和onDependentViewChanged()兩個方法。好比AppBarLayout.Behavior 就定義了這兩個關鍵方法。這個behavior用於當滾動發生的時候讓AppBarLayout發生改變。
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return dependency instanceof AppBarLayout; } public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { // check the behavior triggered android.support.design.widget.CoordinatorLayout.Behavior behavior = ((android.support.design.widget.CoordinatorLayout.LayoutParams) dependency.getLayoutParams()).getBehavior(); if (behavior instanceof AppBarLayout.Behavior) { // do stuff here } }
理解如何實現這些自定義behavior的最好途徑是研究AppBarLayout.Behavior 和 FloatingActionButtion.Behavior。雖然這些源代碼尚未放出來,可是你可使用Android Studio 1.2集成的反編譯器來查看。