CoordinatorLayout與滾動的處理
英文原文:https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout
這篇文章專門講解和CoordinatorLayout相關的知識點,這也是Design Support Library中最重要與最難的部分。
概覽
CoordinatorLayout 實現了多種Material Design中提到的滾動效果。目前這個框架提供了幾種不用寫動畫程式碼就能工作的方法,這些效果包括:
-
讓浮動操作按鈕上下滑動,為Snackbar留出空間。
-
擴充套件或者縮小Toolbar或者頭部,讓主內容區域有更多的空間。
-
控制哪個view應該擴充套件還是收縮,以及其顯示大小比例,包括視差滾動效果動畫。
設定
首先確保遵循了Design Support Library的使用說明。
浮動操作按鈕與Snackbar
CoordinatorLayout可以用來配合浮動操作按鈕的 layout_anchor 和 layout_gravity屬性創造出浮動效果,layout_anchor 指定參照物, anchorGravity 指定相對於參照物的位置,設定為 bottom|right則表示將FloatingActionButton放置於參照物的右下角。詳情請參見浮動操作按鈕指南。
當Snackbar在顯示的時候,往往出現在螢幕的底部。為了給Snackbar留出空間,浮動操作按鈕需要向上移動。
只要使用CoordinatorLayout作為基本佈局,將自動產生向上移動的動畫。浮動操作按鈕有一個 預設的 behavior來檢測Snackbar的新增並讓按鈕在Snackbar之上呈現上移與Snackbar等高的動畫。
- <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>
Toolbar的擴充套件與收縮
首先需要確保你不是使用已經過時的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>
響應滾動事件
接下來,我們必須使用一個容器佈局:AppBarLayout來讓Toolbar響應滾動事件。
- <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目前必須是第一個巢狀在CoordinatorLayout裡面的子view(現在貌似不是這樣子,正確的理解是:AppBarLayout必須是CoordinatorLayout的直接子View)。
然後,我們需要定義AppBarLayout與滾動檢視之間的聯絡。在RecyclerView或者任意支援巢狀滾動的view比如NestedScrollView上新增app:layout_behavior。support
library包含了一個特殊的字串資源@string/appbar_scrolling_view_behavior,它的值為android.support.design.widget.AppBarLayout$ScrollingViewBehavior ,指向AppBarLayout.ScrollingViewBehavior,用來通知AppBarLayout
這個特殊的view何時發生了滾動事件,這個behavior需要設定在觸發滾動事件的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">
當CoordinatorLayout發現RecyclerView中定義了這個屬性,它會搜尋自己所包含的其他view,看看是否有view與這個behavior相關聯。AppBarLayout.ScrollingViewBehavior描述了RecyclerView與AppBarLayout之間的依賴關係。RecyclerView的任意滾動事件都將觸發AppBarLayout或者AppBarLayout裡面view的改變。
AppBarLayout裡面定義的view只要設定了app:layout_scrollFlags屬性,就可以在RecyclerView滾動事件發生的時候被觸發:
- <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>
app:layout_scrollFlags屬性裡面必須至少啟用scroll這個flag,這樣這個view才會滾動出螢幕,否則它將一直固定在頂部。可以使用的其他flag有:
-
enterAlways: 一旦向上滾動這個view就可見。
-
enterAlwaysCollapsed: 顧名思義,這個flag定義的是何時進入(已經消失之後何時再次顯示)。假設你定義了一個最小高度(minHeight)同時enterAlways也定義了,那麼view將在到達這個最小高度的時候開始顯示,並且從這個時候開始慢慢展開,當滾動到頂部的時候展開完。
-
exitUntilCollapsed: 同樣顧名思義,這個flag時定義何時退出,當你定義了一個minHeight,這個view將在滾動到達這個最小高度的時候消失。
記住,要把帶有scroll flag的view放在前面,這樣收回的view才能讓正常退出,而固定的view繼續留在頂部。
此時,你應該注意到我們的Toolbar能夠響應滾動事件了。
譯者注:另外,ScrollingViewBehavior除了能處理滾動行為,還能使設定了app:layout_behavior="@string/appbar_scrolling_view_behavior"的view顯示在AppBarLayout的下面。而不是疊加在AppBarLayout上。
製造摺疊效果
如果想製造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>
自定義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發生改變。
- 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整合的反編譯器來檢視。
相關文章
- 用 CoordinatorLayout 處理滾動
- (譯)使用CoordinatorLayout處理滾動
- OverScroll彈性滾動和慣性滾動效果的實現原理——CoordinatorLayout+Behavior
- selenium中JS如何處理滾動條JS
- 回滾段完蛋了的處理
- Oracle提交和回滾處理Oracle
- 20 個用於處理頁面滾動效果的 jQuery 外掛jQuery
- 汙水處理自動化控制與汙水處理廠集中控制
- win10系統iframe滾動條閃動怎麼處理_win10系統iframe滾動條閃動如何修復Win10
- echarts圖表漸變色 、及X軸滾動條樣式處理Echarts
- scrollIntoView 與平滑滾動View
- 影片美顏SDK動態處理技術與靜態處理技術
- 回滾段表空間損壞處理(ORA-01552)處理方法
- Oracle空串與null的處理OracleNull
- 使用 CoordinatorLayout 實現複雜聯動效果
- 灰度部署、滾動部署與藍綠部署
- 當 Vue 處理陣列與處理純物件的方式一樣Vue陣列物件
- 【問題處理】“NOT IN”與“NULL”的邂逅Null
- Ext實現滾動條一直處於底部的方法
- ITL與事務處理
- div滾動條樣式,水平滾動
- 隱藏滾動條保留滾動效果
- RecyclerView滾動位置,滾動速度設定View
- android CoordinatorLayout使用Android
- php 與 nginx 的兩種處理方式PHPNginx
- 【Oracle】死鎖的產生與處理Oracle
- iOS UITableViewCell允許滑動的處理iOSUIView
- 怎樣處理包含的動態模板
- 9.動態樣式的處理
- Henry的VB.NET之旅(十四)—動態關聯事件與處理程式事件
- 大資料爭論:批處理與流處理的C位之戰大資料
- js如何實現將滾動條處於最下端JS
- css隱藏滾動條並可以滾動CSS
- scrollable滾動條向下滾動至底部
- 移動端div跟隨滾動條滾動(自制
- md在web良好展示的處理,三種實現定位時平緩滾動的方法(vue + Element ui + mark.js)WebVueUIJS
- 1.21 JQuery4:滑鼠事件與滾動事件jQuery事件
- 【故障處理】ORA- 2730*,status 12故障分析與處理