CoordinatorLayout與滾動的處理

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0717/3196.html

概覽

CoordinatorLayout實現了多種Material Design中提到的滾動效果。目前這個框架提供了幾種不用寫動畫代碼就能工作的方法,這些效果包括:

讓浮動操作按鈕上下滑動,為Snackbar留出空間。

擴展或者縮小Toolbar或者頭部,讓主內容區域有更多的空間。

控制哪個view應該擴展還是收縮,以及其顯示大小比例,包括視差滾動效果動畫。

設置

首先確保遵循了Design Support Library的使用說明。

浮動操作按鈕與Snackbar

CoordinatorLayout可以用來配合浮動操作按鈕的?layout_anchor?和?layout_gravity屬性創造出浮動效果,詳情請參見浮動操作按鈕指南。

Snackbar在顯示的時候,往往出現在屏幕的底部。為了給Snackbar留出空間,浮動操作按鈕需要向上移動。

只要使用CoordinatorLayout作為基本布局,將自動產生向上移動的動畫。浮動操作按鈕有一個默認的 behavior來檢測Snackbar的添加并讓按鈕在Snackbar之上呈現上移與Snackbar等高的動畫。

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:id="@+id/rvToDoList"

android:layout_width="match_parent"

android:layout_height="match_parent">

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"/>

Toolbar的擴展與收縮

首先需要確保你不是使用已經過時的ActionBar。務必遵循使用ToolBar作為actionbar這篇文章的指南。同樣,這里也需要CoordinatorLayout作為主布局容器。

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:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

響應滾動事件

接下來,我們必須使用一個容器布局:AppBarLayout來讓Toolbar響應滾動事件。

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:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

注意:根據官方的谷歌文檔,AppBarLayout目前必須是第一個嵌套在CoordinatorLayout里面的子view(現在貌似不是這樣子,正確的理解是:AppBarLayout必須是CoordinatorLayout的直接子View)。

然后,我們需要定義AppBarLayout與滾動視圖之間的聯系。在RecyclerView或者任意支持嵌套滾動的view比如NestedScrollView上添加app:layout_behavior。support library包含了一個特殊的字符串資源@string/appbar_scrolling_view_behavior,它和AppBarLayout.ScrollingViewBehavior相匹配,用來通知AppBarLayout 這個特殊的view何時發生了滾動事件,這個behavior需要設置在觸發事件(滾動)的view之上。

android:id="@+id/rvToDoList"

android:layout_width="match_parent"

android:layout_height="match_parent"

app:layout_behavior="@string/appbar_scrolling_view_behavior">

當CoordinatorLayout發現RecyclerView中定義了這個屬性,它會搜索自己所包含的其他view,看看是否有view與這個behavior相關聯。AppBarLayout.ScrollingViewBehavior描述了RecyclerView與AppBarLayout之間的依賴關系。RecyclerView的任意滾動事件都將觸發AppBarLayout或者AppBarLayout里面view的改變。

AppBarLayout里面定義的view只要設置了app:layout_scrollFlags屬性,就可以在RecyclerView滾動事件發生的時候被觸發:

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:fitsSystemWindows="true"

android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

android:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

app:layout_scrollFlags="scroll|enterAlways"/>

app:layout_scrollFlags屬性里面必須至少啟用scroll這個flag,這樣這個view才會滾動出屏幕,否則它將一直固定在頂部。可以使用的其他flag有:

enterAlways: 一旦向下滾動這個view就可見。

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

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

記住,要把帶有scroll flag的view放在前面,這樣收回的view才能讓正常退出,而固定的view繼續留在頂部。

此時,你應該注意到我們的Toolbar能夠響應滾動事件了。

制造折疊效果

如果想制造toolbar的折疊效果,我們必須把Toolbar放在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:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

app:layout_scrollFlags="scroll|enterAlways">

現在效果就成了:

通常,我們我們都是設置Toolbar的title,而現在,我們需要把title設置在CollapsingToolBarLayout上,而不是Toolbar。

CollapsingToolbarLayoutcollapsingToolbar=

(CollapsingToolbarLayout)findViewById(R.id.collapsing_toolbar);

collapsingToolbar.setTitle("Title");

制造視差效果

CollapsingToolbarLayout還能讓我們做出更高級的動畫,比如在里面放一個ImageView,然后在它折疊的時候漸漸淡出。同時在用戶滾動的時候title的高度也會隨著改變。

為了制造出這種效果,我們添加一個定義了app:layout_collapseMode="parallax"?屬性的ImageView。

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:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

app:layout_scrollFlags="scroll|enterAlways">

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"/>

自定義Behavior

CoordinatorLayout 與浮動操作按鈕中我們討論了一個自定義behavior的例子。注: 譯文http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0718/3197.html

CoordinatorLayout的工作原理是搜索定義了CoordinatorLayout Behavior的子view,不管是通過在xml中使用app:layout_behavior標簽還是通過在代碼中對view類使用@DefaultBehavior修飾符來添加注解。當滾動發生的時候,CoordinatorLayout會嘗試觸發那些聲明了依賴的子view。

要自己定義CoordinatorLayout?Behavior,你需要實現layoutDependsOn() 和onDependentViewChanged()兩個方法。比如AppBarLayout.Behavior 就定義了這兩個關鍵方法。這個behavior用于當滾動發生的時候讓AppBarLayout發生改變。

publicbooleanlayoutDependsOn(CoordinatorLayoutparent,Viewchild,Viewdependency){

returndependencyinstanceofAppBarLayout;

}

publicbooleanonDependentViewChanged(CoordinatorLayoutparent,Viewchild,Viewdependency){

//?check?the?behavior?triggered

android.support.design.widget.CoordinatorLayout.Behaviorbehavior=((android.support.design.widget.CoordinatorLayout.LayoutParams)dependency.getLayoutParams()).getBehavior();

if(behaviorinstanceofAppBarLayout.Behavior){

//?do?stuff?here

}

}

理解如何實現這些自定義behavior的最好途徑是研究AppBarLayout.Behavior 和?FloatingActionButtion.Behavior。雖然這些源代碼還沒有放出來,但是你可以使用Android Studio 1.2集成的反編譯器來查看。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容