本博文專門解說和CoordinatorLayout相關的知識點,這也是Design Support Library中最重要與最難的部分。
概覽
CoordinatorLayout實現了多種Material Design中提到的滾動效果。眼下這個框架提供了幾種不用寫動畫代碼就能工作的方法,這些效果包含:
讓浮動操作按鈕上下滑動,為Snackbar留出空間
擴展或者縮小Toolbar或者頭部,讓主內容區域有很多其它的空間。
控制哪個view應該擴展還是收縮。以及其顯示大小比例。包含視差滾動效果parallax scrolling effects 動畫。
Code Samples
官方為我們提供了一個美麗的demo ,使用了 CoordinatorLayout
和其它的 design support library特性.
詳情請查看github
效果圖
Setup
Make sure to follow the Design Support Library instructions first.
Floating Action Buttons and Snackbars
The CoordinatorLayout
can be used to create floating effects using the layout_anchor
and layout_gravity
attributes. See the Floating Action Buttons guide for more information.
When a Snackbar is rendered, it normally appears at the bottom of the visible screen. To make room, the floating action button must be moved up to provide space.
So long as the CoordinatorLayout is used as the primary layout, this animation effect will occur for you automatically. The floating action button has a default behavior that detects Snackbar views being added and animates the button above the height of the Snackbar.
Code
activity_fab__snackar.xml
<?xml version="1.0" encoding="utf-8"?>
<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.support.v7.widget.RecyclerView
android:id="@+id/rvToDoList"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"
android:src="@drawable/gur_project_10"
app:layout_anchor="@id/rvToDoList"
app:layout_anchorGravity="bottom|right|end"
app:layout_behavior="demo.turing.com.materialdesignwidget.floatingActionButton.ScrollAwareFABBehavior"/>
</android.support.design.widget.CoordinatorLayout>
Fab_SnackarAct.java
public class Fab_SnackarAct extends AppCompatActivity {
private RecyclerView recyclerView;
private FloatingActionButton floatingActionButton;
private CoordinatorLayout coordinatorLayout ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fab__snackar);
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.main_content);
floatingActionButton = (FloatingActionButton) findViewById(R.id.floatingActionButton);
recyclerView = (RecyclerView) findViewById(R.id.rvToDoList);
// 線性布局
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 設置適配器,填充數據
recyclerView.setAdapter(new NormalRecyclerViewAdapter(this));
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view,"HELLO",Snackbar.LENGTH_SHORT).show();
}
});
}
}
關鍵點
- 根布局必須為CoordinatorLayout
- FloatingActionButton設置 app:layout_anchor和app:layout_anchorGravity屬性
- app:layout_behavior這個屬性也能夠不加也能實現點擊floatingActionButton彈出Snackbar。fab自己主動上移的效果,app:layout_behavior的為自己定義的效果,當下滑時。fab消失,上滑時fab顯示,詳情請查看本人博客 Floating Action Button-Android M新控件
執行圖
Expanding and Collapsing Toolbars(Toolbar的擴展與收縮)
- The first step is to make sure you are not using the deprecated ActionBar. Make sure to follow the Using the ToolBar as ActionBar guide.
- Also make sure that the CoordinatorLayout is the main layout container.
<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>
Responding to Scroll Events
Next, we must make the Toolbar responsive to scroll events using a container layout called AppBarLayout:
接下來。我們必須使用一個容器布局: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>
Note: AppBarLayout
currently expects to be the first child nested within a CoordinatorLayout according to the official Google docs.
注意:依據官方的谷歌文檔。AppBarLayout眼下必須是第一個嵌套在CoordinatorLayout里面的子view。
Next, we need to define an association between the AppBarLayout and the View that will be scrolled. Add an app:layout_behavior
to a RecyclerView or any other View capable of nested scrolling such as NestedScrollView 。
The support library contains a special string resource @string/appbar_scrolling_view_behavior
that maps to AppBarLayout.ScrollingViewBehavior, which is used to notify the AppBarLayout when scroll events occur on this particular view. The behavior must be established on the view that triggers the event.
然后。我們須要定義AppBarLayout與滾動視圖之間的聯系。在RecyclerView或者隨意支持嵌套滾動的view比方NestedScrollView上加入app:layout_behavior
。support library包含了一個特殊的字符串資源@string/appbar_scrolling_view_behavior,它和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就可見。
Normally, the Toolbar only appears when the list is scrolled to the top as shown below:
- enterAlwaysCollapsed: 顧名思義,這個flag定義的是何時進入(已經消失之后何時再次顯示)。如果你定義了一個最小高度(minHeight)同一時候enterAlways也定義了。那么view將在到達這個最小高度的時候開始顯示,而且從這個時候開始慢慢展開,當滾動到頂部的時候展開完。
exitUntilCollapsed: 相同顧名思義,這個flag時定義何時退出。當你定義了一個minHeight,這個view將在滾動到達這個最小高度的時候消失。
snap:Using this option will determine what to do when a view only has been partially reduced. If scrolling ends and the view size has been reduced to less than 50% of its original, then this view to return to its original size. If the size is greater than 50% of its sized, it will disappear completely.
記住,要把帶有scroll flag的view放在前面,這樣收回的view才干讓正常退出,而固定的view繼續留在頂部。
此時,你應該注意到我們的Toolbar能夠響應滾動事件了。
Creating Collapsing Effects(制造折疊效果)
如果想制造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");
Note that when using CollapsingToolbarLayout
, the status bar should be made translucent (API 19) or transparent (API 21) as shown in this file. In particular, the following styles should be set in res/values-xx/styles.xml
as illustrated:
<!-- res/values-v19/styles.xml -->
<style name="AppTheme" parent="Base.AppTheme"> <item name="android:windowTranslucentStatus">true</item> </style>
<!-- res/values-v21/styles.xml -->
<style name="AppTheme" parent="Base.AppTheme"> <item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@android:color/transparent</item> </style>
Creating Parallax Animations(制造視差效果)
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>
Custom Behaviors (自己定義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
}
}
英文原文:
https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout