轉: Material Design 中最重要的 CoordinatorLayout 佈局 (1)
承接前幾天的博客:
下面博客內容可能要有以下預備知識,你也可瞭解完這一篇內容以後再回過頭看這些:
ToolBar使用:http://blog.csdn.net/rosechan/article/details/51511376
SnackBar&&FloatingActionButton:http://blog.csdn.net/rosechan/article/details/51520325
NavigationView:http://blog.csdn.net/rosechan/article/details/51534797
TabLayout:http://blog.csdn.net/rosechan/article/details/51568130
本文帶來實現MaterialDesign中最重要的一個佈局,CoordinatorLayout-協調佈局,人如其名,這個佈局主要用於協調內部的各個子控件進行交互,通過設置子控件的behavior(下面會講到)來操控子控件的一些操作和動畫,孔子曾經說過:
CoordinatorLayout is a super-powered FrameLayout.
以下面幾個例子來說明CoordinatorLayout的基本使用:
1-SnackBar和FloatingActionButton交互:
在前幾天的博客中講到了這個,效果如下:
FAB隨着SnackBar的出現和消失而上下滑動。這篇博客講到了將FAB放在CoordinatorLayout佈局中,再將SnackBar.make()的第一個參數傳入CoordinatorLayout對象即可。那麼爲什麼將FAB放在CoordinatorLayout中就讓其發生改變呢,咋們從源碼看起,我們可以在FloatingActionButton源碼中看到有一個Behavior實現類:
從註釋就可以看到,這個Behavior類會在FAB實例化時創建,其主要的功能就是讓FAB與SnackBar交互,防止SnackBar遮擋FAB。
而在CoordinatorLayout中就包含了這個Behavior抽象類,並使用這個Behavior類來操縱內部空間的行爲:
這也就是爲什麼FAB外面簡單套一層CoordinatorLayout就會有交互效果的原因 ~
2-ToolBar隨界面上滑而收縮隱藏
效果如圖:
可以看到Toolbar隨着內容部分的滑動產生了收縮隱藏,要實現這個效果,只需要修改xml文件,添加一些屬性:
<android.support.design.widget.coordinatorlayout android:layout_width="match_parent" android:layout_height="match_parent">
<android.support.design.widget.appbarlayout android:layout_width="match_parent" android:layout_height="wrap_content">
<android.support.v7.widget.toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimary" <!--就是↓這個--="">
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<android.support.design.widget.tablayout android:id="@+id/tabLayout" app:tabindicatorcolor="#ffffff" app:tabselectedtextcolor="#ffffff" app:tabtextcolor="#cdcdcd" app:tabgravity="center" app:tabmode="scrollable" android:layout_width="match_parent" android:layout_height="wrap_content">
</android.support.design.widget.tablayout>
</android.support.v7.widget.toolbar></android.support.design.widget.appbarlayout>
<android.support.v4.view.viewpager <!--在這裏↓--="">
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.view.viewpager></android.support.design.widget.coordinatorlayout>
裏面涉及到之前博客的遺漏內容,一個個解析下。
首先,AppBarLayout是什麼鬼,爲什麼要拿他包裹ToolBar和TabLayout,咋們再看源碼發現,AppBarLayout中也有一個內置的Behavior類,而ToolBar和TabLayout中沒有,所以我們可以得出,正因爲AppBarLayout有Behavior,才能與CoordinatorLayout產生交互,由此我們可以推斷AppBarLayout正是爲了讓協調佈局和更早的toolbar之類的佈局可以兼容工作才產生的。而僅僅使用AppBarLayout包裹toolbar和tablayout還不夠,google親爹說了:
Children should provide their desired scrolling behavior through setScrollFlags(int) and the associated layout xml attribute: app:layout_scrollFlags.
意思說AppBarLayout的子控件還要設置layout_scrollFlags屬性(或者通過setScrollFlags( ))才能達到其想要的滑動行爲效果。
所以我們在ToolBar標籤里加上一句:
app:layout_scrollFlags="scroll|enterAlways"
就可以實現如圖的效果~這裏注意命名空間爲app,在AndroidStudio會自動設置爲res-auto,Eclipse玩家要自己設置命名空間了。
那麼這個layout_scrollFlags裏面屬性值到底是啥?
通過提示我們可以看到有五種flag值:
2.1 五種FLAG:
- SCROLL_FLAG_ENTER_ALWAYS
- SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED
- SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
- SCROLL_FLAG_SCROLL
- SCROLL_FLAG_SNAP
這五種值分別對應的是AppBarLayout裏控件的五種行爲方式,如下~
-
FLAG_SCROLL:這個是其他控件想要有滑動隱藏行爲的基礎,下面的其他屬性值,一定要設置了scroll後纔有效果,所以設置屬性要像這樣~
app:layout_scrollFlags=”scroll|enterAlways”
-
ENTER_ALWAYS: 當屏幕下滑,設置了這個行爲的控件(比如toolbar)就會立馬滑回屏幕,類似於快速返回的效果,而且不管下面的滑動組件(比如ScrollView是否正在滑動).
-
ENTER_ALWAYS_COLLAPSED: 當你的視圖已經設置minHeight屬性又使用此標誌時,你的視圖只能以最小高度進入,只有當滾動視圖到達頂部時才擴大到完整高度。通過這個示例圖就明白了:
可以看到toolbar設置了minHeight屬性爲10dp,看到toolbar向上偏移了10dp,所以進入時toolbar其實只進入了10dp,且下拉過程中,只有當滑到頂了,此時繼續滑toolbar纔會顯示出來(對比上面enterAlways~)。
-
EXIT_UNTIL_COLLAPSED:滑動的時候這個空間會收縮,並且最多隻能收縮到minHeight如下圖:
-
SNAP: 這個屬性讓控件變得有彈性,如果控件(比如toolbar)顯示了75%的高度,就會彈出顯示出來,如果只有25%顯示,就會收縮隱藏起來,如圖所示。
同理,設置給tabLayout也有效果,所以使用這五種效果可以很好的配合CoordinatorLayout實現各種效果~
2.2設置layout_behavior屬性
寫到這裏我纔想到本來這個應該放前面寫的,不過影響不大。如果你是照着上面一步步邊敲邊實踐的,那麼會踩到一個坑,CoordinatorLayout裏的佈局會被toolBar或者AppBarLayout擋住~
解決方法:在CoordinatorLayout中的可滑動佈局添加(比如Viewpager中添加下面的標籤,注意命名空間):
app:layout_behavior="@string/appbar_scrolling_view_behavior"
看到這裏已經很熟悉了,behavior你穿上馬甲我也認識你!又是一個不和協調佈局兼容的控件,所以要加上這個屬性,才能和協調佈局中的其他組件配合,而傳入的值呢,這麼長一串是啥,根據剛剛查看Behavior源碼我們知道,CoordinatorLayout是根據傳入的Behavior行爲的類名,利用反射來實例化行爲對象,那麼同樣的,這裏這麼長一串也是一種行爲,來自於AppBarLayout.ScrollingViewBehavior:
查看這個類的源碼:
/**
* Behavior which should be used by {@link View}s which can scroll vertically and support
* nested scrolling to automatically scroll any {@link AppBarLayout} siblings.
*/
public static class ScrollingViewBehavior extends HeaderScrollingViewBehavior {
.....
}
註釋正是說這個Behavior可以讓其他滑動控件可以與之兼容工作!(~搞到這裏有一種懸疑片解謎的感覺了 ~(≧▽≦)/~,一切都是以CoordinatorLayout爲核心,而真正的罪犯又來自Behavior,這個幕後主使纔是操控一切子控件行爲的根源~)
Tips:
到這裏你也知道了 CoordinatorLayout不能和很多控件使用,比如要是內容部分放ListView,就算設置了layout_behavior也沒用,取而代之使用RecyclerView或者NestedScrollView,在上例的內容如果使用ViewPager的話,ViewPager的子佈局應使用NestedScrollView代替ScrollView才能保證可以滑動。
2.3綜上所述:
爲了使得Toolbar有滑動效果,必須做到如下三點:
1. CoordinatorLayout作爲佈局的父佈局容器。
2. 給需要滑動的組件設置 app:layout_scrollFlags=”scroll|enterAlways” 屬性。
3. 給滑動的組件設置app:layout_behavior屬性
3-使用CollapsingToolbarLayout實現炫酷頭部效果~
3.1效果:
很美,很華麗,很動人。節省時間,直接先上用法:
3.2 佈局文件:
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.chan.iwfu_md_news.activity.NewsDetailActivity">
<android.support.design.widget.appbarlayout android:layout_width="match_parent" android:layout_height="256dp" android:fitssystemwindows="true" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<!--關鍵在這裏↓-->
<android.support.design.widget.collapsingtoolbarlayout android:layout_width="match_parent" android:layout_height="match_parent" app:collapsedtitlegravity="center" app:contentscrim="@color/colorPrimary" app:layout_scrollflags="scroll|exitUntilCollapsed">
<imageview android:id="@+id/iv_news_detail" android:layout_width="match_parent" android:layout_height="match_parent" android:scaletype="centerCrop" android:src="@mipmap/shibai" app:layout_collapsemode="parallax" app:layout_collapseparallaxmultiplier="0.5">
<android.support.v7.widget.toolbar android:id="@+id/toolbar_newsDetail" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="#00000000" <!--關鍵在這裏↓--="">
app:layout_collapseMode="pin"
app:popupTheme="@style/Theme.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
</android.support.v7.widget.toolbar></imageview></android.support.design.widget.collapsingtoolbarlayout>
</android.support.design.widget.appbarlayout>
<android.support.v4.widget.nestedscrollview android:layout_width="match_parent" android:layout_height="match_parent" android:padding="12dp" <!--關鍵在這裏↓--="">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<webview android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="wrap_content">
</webview>
</android.support.v4.widget.nestedscrollview>
<android.support.design.widget.floatingactionbutton android:layout_height="wrap_content" android:layout_width="wrap_content" <!--關鍵在這裏↓--="">
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
android:src="@drawable/ic_done"
android:layout_margin="20dp"
android:clickable="true"/>
</android.support.design.widget.floatingactionbutton></android.support.design.widget.coordinatorlayout>
這是一個全新的頁面,和上面的栗子2沒有多大關係,不過以後也可以是由首頁跳轉到這個界面來顯示詳情。在這個佈局文件裏,主要使用到了:
CollapsingToolbarLayout ,NestedScrollView這兩個新東西,
查api:
- collaspsingToolbarLayout:是toolbar的包裝類,繼承了collapsing app bar,被設計直接作爲AppBarLayout的子佈局使用,以後也推薦用AppBarLayout-CollapsingToobarLayout-Toolbar這樣的結構使用,
3.3 CollapsingToolbarLayout 提供以下屬性和方法使用:
-
Collapsing title:ToolBar的標題,當CollapsingToolbarLayout全屏沒有摺疊時,title顯示的是大字體,在摺疊的過程中,title不斷變小到一定大小的效果。你可以調用setTitle(CharSequence)方法設置title。
-
Content scrim:ToolBar被摺疊到頂部固定時候的背景,你可以調用setContentScrim(Drawable)方法改變背景或者 在屬性中使用 app:contentScrim=”?attr/colorPrimary”來改變背景。
-
Status bar scrim:狀態欄的背景,調用方法setStatusBarScrim(Drawable)。即實現沉浸狀態欄(或者叫透明狀態欄吧~不懂具體叫啥),貌似5.0以上纔有效果。
-
Parallax scrolling children:CollapsingToolbarLayout滑動時,子視圖的視覺差,可以通過屬性app:layout_collapseParallaxMultiplier=”0.6”改變。值de的範圍[0.0,1.0],值越大視察越大。
-
CollapseMode :子視圖的摺疊模式,在子視圖設置,有兩種“pin”:固定模式,在摺疊的時候最後固定在頂端;“parallax”:視差模式,在摺疊的時候會有個視差摺疊的效果。我們可以在佈局中使用屬性app:layout_collapseMode=”parallax”來改變。
在佈局文件collapsingToolbarLayout中使用ImageView作爲背景圖,設置上面的一些屬性,就可以達到我們要的這種華麗的效果。
就像scrollView,不過相比之下他更兼容新老版本的控件,更好的與後面的控件包括CoordinatorLayout配合使用.
3.5 FAB設置:
CoordinatorLayout提供app:layout_anchor,可以設置子視圖的錨點,一般和layout_anchorGravity聯用,這樣這個組件就有懸浮於錨點佈局的感覺了。並且會隨着錨點佈局而改變(如本例的AppBarLayout和FAB)。
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
Tip:
關於視差童鞋們自己試一試,這個不好用語言描述,不過對比一下還是會很有感覺的。
最後:
這篇到此就結束了,主要講述了CoordinatorLayout協調佈局這個MD風格控件的中流砥柱的作用,碼字不易,明天再來一篇關於自定義Behavior,實現我們自己的佈局交互動畫效果~
感謝你能耐心看到這裏~~~