Material Design 中最重要的 CoordinatorLayout 佈局 (1)

轉: 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 提供以下屬性和方法使用:

  1. Collapsing title:ToolBar的標題,當CollapsingToolbarLayout全屏沒有摺疊時,title顯示的是大字體,在摺疊的過程中,title不斷變小到一定大小的效果。你可以調用setTitle(CharSequence)方法設置title。

  2. Content scrim:ToolBar被摺疊到頂部固定時候的背景,你可以調用setContentScrim(Drawable)方法改變背景或者 在屬性中使用 app:contentScrim=”?attr/colorPrimary”來改變背景。

  3. Status bar scrim:狀態欄的背景,調用方法setStatusBarScrim(Drawable)。即實現沉浸狀態欄(或者叫透明狀態欄吧~不懂具體叫啥),貌似5.0以上纔有效果。

  4. Parallax scrolling children:CollapsingToolbarLayout滑動時,子視圖的視覺差,可以通過屬性app:layout_collapseParallaxMultiplier=”0.6”改變。值de的範圍[0.0,1.0],值越大視察越大。

  5. 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,實現我們自己的佈局交互動畫效果~

感謝你能耐心看到這裏~~~


發佈了38 篇原創文章 · 獲贊 25 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章