天天看點

談談Material Design之CoordinatorLayout本文主要介紹一下如何使用CoordinatorLayout

本文主要介紹一下如何使用CoordinatorLayout

先看看官方是怎麼介紹Material Design的

We challenged ourselves to create a visual language for our users that synthesizes the classic principles of good design with the innovation and possibility of technology and science. This is material design. This spec is a living document that will be updated as we continue to develop the tenets and specifics of material design.

通過上面的這段英文相信大家對Material Design或多或少都有一定的認識了吧!大概的意思也就是google努力的幫你設計出一套很好視圖設計規範,你按這個規範來咯~~~

我覺得我們需要關注的控件也就下面4個吧~

  • SnackBar:一個類似于Toast的控件,下文會提及
  • FloatingActionButton:懸浮按鈕
  • CoordinatorLayout:也就是本篇博文的豬腳咯~~
  • Tablayout:本篇不聊

講了這麼多廢話,那麼我們正式進入今天的主題吧!

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

  1. 當snackbar顯示的時候,浮動按鈕上移,給snackbar留出位置:效果如下
    談談Material Design之CoordinatorLayout本文主要介紹一下如何使用CoordinatorLayout
  2. 擴充或者縮小Toolbar或者頭部,讓主内容區域有更多的空間:效果如下
    談談Material Design之CoordinatorLayout本文主要介紹一下如何使用CoordinatorLayout
  3. 控制哪個view應該擴充還是收縮,以及其顯示大小比例,包括視差滾動效果動畫。
    談談Material Design之CoordinatorLayout本文主要介紹一下如何使用CoordinatorLayout

自行引入Design Support Library,不清楚請自行網補

首先,我們看第一種效果

布局代碼

<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.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        >
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            app:layout_scrollFlags="scroll|enterAlways"
            android:layout_width="match_parent"
            android:background="?attr/colorPrimary"
            android:layout_height="wrap_content"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            />
    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        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/recyclerview"
        app:layout_anchorGravity="bottom|right|end"/>

</android.support.design.widget.CoordinatorLayout>
           
嘻嘻,今天豬腳終于亮相了,首先我們使用了CoordinatorLayout作為根布局,CoordinatorLayout可以用來配合浮動操作按鈕的 layout_anchor 和 layout_gravity屬性創造出浮動效果,隻要使用CoordinatorLayout作為基本布局,将自動産生向上移動的動畫。浮動操作按鈕有一個 預設的 behavior來檢測Snackbar的添加并讓其在Snackbar之上呈現上移與Snackbar等高的動畫。
咳咳,這個我相信大家都能懂,那麼我們來說說FloatingActionButton這個控件。

當我們的項目需要一個圓形的Button, 你可能會想到用自定義Shape的方式去做,但那樣文本的顯示不好居中,這時估計就想到用自定義控件去解決了。以上都是廢話,google給我們提供了FloatingActionButton可以輕松的建立圓形Button,而且更牛x的是FloatingActionButton具有更絢麗的效果。

FloatingActionButton繼承自ImageView,是以你懂的,ImageView的屬性我們闊以直接拿來用咯,so。。如果我們需要整個圓形的ImageView也當然闊以直接用這個咯~~

FloatingActionButton的屬性主要有
  1. app:backgroundTint是指定預設的背景顔色
  2. app:rippleColor是指定點選時的背景顔色
  3. app:borderWidth border的寬度
  4. app:fabSize是指FloatingActionButton的大小,可選normal|mini
  5. app:elevation 可以看出該空間有一個海拔的高度
  6. app:pressedTranslationZ 哈,按下去時的z軸的偏移
<android.support.design.widget.FloatingActionButton
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@mipmap/ic_launcher"
        app:backgroundTint="#FF00FF00"
        app:rippleColor="#FF0000FF"
        app:borderWidth="0dp"
        app:fabSize="normal"
        app:elevation="10dp"
        app:pressedTranslationZ="20dp"/>
           
傳說中的一圖勝千言
談談Material Design之CoordinatorLayout本文主要介紹一下如何使用CoordinatorLayout
卡卡的 湊合看吧!!

第二種效果 Toolbar的擴充與收縮

先看效果吧
談談Material Design之CoordinatorLayout本文主要介紹一下如何使用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.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        >
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            app:layout_scrollFlags="scroll|enterAlways"
            android:layout_width="match_parent"
            android:background="?attr/colorPrimary"
            android:layout_height="wrap_content"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            />
        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            app:tabMode="scrollable"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

        </android.support.design.widget.TabLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@mipmap/ic_launcher"
        app:backgroundTint="#FF00FF00"
        app:rippleColor="#FF0000FF"
        app:borderWidth="0dp"
        app:fabSize="normal"
        app:elevation="10dp"
        app:pressedTranslationZ="20dp"
        app:layout_anchor="@id/recyclerview"
        app:layout_anchorGravity="bottom|right|end"/>

</android.support.design.widget.CoordinatorLayout>
           
首先你必須保證用toolbar替代actionbar,至于toolbar的具體使用,也不是本篇的重點,不清楚的童鞋闊以自行網補(話說這部落格到底有木有幹貨~~啥都要網補)
接下來,我們必須使用一個容器布局:AppBarLayout來讓Toolbar響應滾動事件。請注意:AppBarLayout必須是CoordinatorLayout的直接子View。
然後,我們需要定義AppBarLayout與滾動視圖之間的聯系。在RecyclerView或者任意支援嵌套滾動的view(比如NestedScrollView)上添加app:layout_behavior。support library包含了一個特殊的字元串資源@string/appbar_scrolling_view_behavior(此處是反射),它和AppBarLayout.ScrollingViewBehavior相比對,用來通知AppBarLayout 這個特殊的view何時發生了滾動事件。
這個behavior需要設定在觸發事件(滾動)的view之上。(注意上面提到的嵌套滾動~~~~比如我們常用的scrollView、listview都是屬于不支援嵌套滾動的)
<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的改變。

細心的你不知道是否已經發現~額 toolbar有

這樣一條屬性。app:layout_scrollFlags,什麼玩意兒,聽我慢慢道來。前面我們提到RecyclerView的任意滾動事件都将觸發AppBarLayout或者AppBarLayout裡面view的改變。那麼,AppBarLayout裡面的子View到底以怎麼樣的方式進行滾動呢?此時這個屬性就起作用了!!!

那麼我們看看這個屬性的屬性值都用哪些

  1. scroll 誰要滾出螢幕,誰就設定這個值
  2. enterAlways 其他向上滑動時,可以立即顯示出來
  3. exitUntilCollapsed 将關閉滾動直到它被折疊起來(有 minHeight) 并且一直保持這樣
  4. enterAlwaysCollapsed 定義了 View 是如何回到螢幕的,當你的 view 已經聲明了一個最小高度(minHeight) 并且你使用了這個标志,你的 View 隻有在回到這個最小的高度的時候才會展開,隻有當 view 已經到達頂部之後它才會重新展開全部高度。

第三種,折疊效果

先上圖!

談談Material Design之CoordinatorLayout本文主要介紹一下如何使用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.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp">

            <ImageView
                android:id="@+id/backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                android:src="@drawable/head"
                app:layout_collapseMode="parallax" />

            <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"
                app:layout_collapseMode="pin" />

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_dialog_email"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|center"/>


</android.support.design.widget.CoordinatorLayout>
           

可以看到,我們将image和toolbar使用CollapsingToolbarLayout包裹起來了

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

CollapsingToolbarLayout collapsingToolbar =
              (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
      collapsingToolbar.setTitle("Title");
           

該控件的的子view必須要有Toolbar,他的作用就是提供一個可折疊的标題欄。通常情況下,該控件會和上面我們說的一些控件搭配使用,達到一種固定的效果。

我們先分析一下上面這段布局,最直覺的,可以看到有一個行為上的協作, 那肯定需要CoordinatorLayout這個控件,而且還會有一個滑動的效果,那肯定是AppBarLayout啦,當然,細心的朋友可能還會看出來,那個圖檔和Toolbar會有一種視差的效果,而且整個banner部分是一種折疊的效果,這就需要CollapsingToolbarLayout這個控件了。

AppBarLayout通過CollapsingToolBarLayout把ImageView和Toolbar作為整個app的标題欄,而且表示滾動辨別的app:layout_scrollFlags=”scroll|exitUntilCollapsed”也是指派給了CollapsingToolbarLayout,mageView有一條屬性app:layout_collapseMode=”parallax”表示這個ImageView以視差的形式折疊(效果上看着貌似就是有點小偏移)。 Toolbar的app:layout_collapseMode=”pin”表示Toolbar在折疊的過程中會停靠頂部(pin的意思是釘住)。 這樣CollapsingToolBarLayout就沒有全部滾出界面。

如果你希望滾動的時候漸變的顔色跟随的是圖檔而不是藍色漸變,在java代碼中使用如下代碼

final CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) findViewById(R.id.ctl);
        ctl.setTitle("Temperate_box");
...
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.banner);
        Palette.generateAsync(bmp, new Palette.PaletteAsyncListener() {
            @Override
            public void onGenerated(Palette palette) {
                Palette.Swatch swatch = palette.getDarkMutedSwatch();
                ctl.setContentScrimColor(swatch.getRgb());
            }
        });
           

ok,打完收工~~~~

繼續閱讀