Android CoordinatorLayout實戰案例學習《一》

在上篇文章中,和大家一起聊了聊AppBarLayout和CoordinatorLayout兩個新控件,以及CoordinatorLayout與FloatingActionButton、Snackbar的使用注意事項。至此,Android Material Design系列的學習已進行到第五篇,大家可以點擊以下鏈接查看之前的文章:

本文繼續以案例的形式學習CoordinatorLayout的使用,配合者為AppBarLayout。文中會介紹一些這種搭配使用的案例下可能出現的問題以及解決方案,目的還是一句話,將我所知的分享出來,讓正在摸索的你少走一些彎路。老路子,先看一下本文要實現的效果圖:

Samples.gif

簡單介紹下,這種設計經常會出現在各個app中,作為主頁顯示,其中主要包含了三個效果:

  • 側拉導航菜單,這個是用v7包中的控件DrawerLayout實現的,不是本文重點,就不作過多說明了;

  • FAB與Snackbar的協調交互,在上篇文章中已經介紹的很詳細了,大家可以另行查看;

  • 列表向上滑動,Toolbar向上隱藏,TabLayout固定于頂部,給內容區域留下更多的展示空間,本文著重講述這種實現。

知識點比較零碎,還是配合著代碼講解比較容易,思路也會比較清晰一些,主要布局文件的實現:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/dl_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <include layout="@layout/include_toolbar" />

            <android.support.design.widget.TabLayout
                android:id="@+id/tl_indicator"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

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

        <android.support.v4.view.ViewPager
            android:id="@+id/vp_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab_add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/dp_16"
            android:onClick="onClickFab"
            android:src="@mipmap/ic_toolbar_add"
            app:backgroundTint="@color/fab_ripple"
            app:layout_anchor="@id/vp_content"
            app:layout_anchorGravity="bottom|right|end" />

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

    <LinearLayout
        android:id="@+id/ll_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:orientation="vertical"
        android:gravity="center"
        android:background="@color/white">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Menu Content"
            android:textColor="@color/black"
            android:textSize="@dimen/sp_16"/>

    </LinearLayout>

</android.support.v4.widget.DrawerLayout>

Android Developer官網中在介紹CoordinatorLayout時有這么一段話:

CoordinatorLayout is intended for two primary use cases:

  1. As a top-level application decor or chrome layout
  2. As a container for a specific interaction with one or more child views

也就是說CoordinatorLayout主要有兩種使用場景,在我理解過來就是,作為Activity布局中的最外層容器和作為指定交互行為的多個子控件的父容器來使用。而本文中的案例就屬于第二種。

要實現這種滑動交互效果,必須要滿足這么幾點:

  1. CoordinatorLayout作為容器布局,來協調children view之間的交互行為;

  2. 使用AppBarLayout并設置其內部需要移出屏幕的View的scrollFlags屬性,在這個例子中也就是給Toolbar設置。由于Toolbar是通用布局代碼,這里我用了include標簽,其包含的布局代碼為:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/tb_toolbar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_56"
    app:titleTextColor="@color/white"
    app:title="@string/app_name"
    app:theme="@style/OverFlowMenuTheme"
    app:popupTheme="@style/AppTheme"
    android:background="@color/blue"
    app:layout_scrollFlags="scroll|enterAlways"/>

可以看到,我添加了app:layout_scrollFlags這個屬性,并將其值設為scroll|enterAlwaysscroll表示滑動型控件向上滑動時toolbar將移出屏幕,enterAlways表示向下滑動時toolbar將重新進入屏幕。由于TabLayout不需要移出屏幕,所以這里就不需要給它設置這個屬性了。需要注意的是:不要將app:layout_scrollFlags屬性單獨設置子include標簽里,而是要放在include所加載的layout布局中,否則這個scrollFlags將失去作用,這與include標簽的使用有關。

  1. 一個特殊的滑動型控件并設置layout_behavior屬性,這里用的是ViewPager。注意,layout_behavior的屬性值用的是系統定義好的固定字符串@string/appbar_scrolling_view_behavior,大家感興趣的自己去翻閱源碼看看,后續介紹behavior時,我再仔細講解。

對于第三點,這里拿出來單獨強調一下,有沒有發現滑動型控件前我用了“特殊”兩個字來修飾!CoordinatorLayout之所以能夠協調Children View之間的交互行為,主要就是依賴于NestedScrolling這個東西,這里涉及到兩個接口類NestedScrollingParentNestedScrollingChild。CoordinatorLayout實現了前者,而CoordinatorLayout的Children核心之一,滑動型控件,實現了后者,所以才能夠做出這個交互行為。關于NestedScrolling,后續再寫文單獨介紹。所以,這個特殊的滑動型控件必須是實現了NestedScrollingChild接口的控件,比如v7包中的RecyclerView,看一下它的定義就知道了:

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild

故,本文中的ViewPager里面的列表控件必須是RecyclerView。如果你僅僅是簡單地使用ListView,還是達不到這樣的效果。聰明如你,肯定又看出了我的措辭,對的,我又用了一個詞:“簡單地使用”,那就說明其實稍作處理,復雜點使用,也能夠使用ListView的。

在API Level 21及更高版本,為了支持NestedScrolling,所有控件的基類View對外新增了一個方法setNestedScrollingEnabled(boolean enabled),所以,我們可以對ListView稍作處理,就能在Android L及以上版本的系統中使用了:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
      listView.setNestedScrollingEnabled(true);
}

或者借助 v4 包中的 ViewCompat 類為 ListView 添加設置,避免版本判斷:

ViewCompat.setNestedScrollingEnabled(listView, true);

但是,這兩種方法均只支持 Android Lollipop 及更高版本,在 pre-lollipop 上是沒有效果的。其實,ListView真的已經過氣了,我們應該全方位掌握RecyclerView的使用,就像Android Studio取代Eclipse一樣。

其他的代碼就很簡單了,就是給DrawerLayout設置ActionBarDrawerToggle,就是圖中ToolBar左側的菜單按鈕。然后用Fragment填充ViewPager,這里就不貼代碼了,工程Demo都在GitHub上,大家可以自己下載參考。

其實這個案例的實現還是蠻簡單的,文中零零碎碎地講述了很多使用過程中的細節技巧,幫助大家解決實際問題。下篇文章繼續使用案例,介紹CoordinatorLayout的使用方法,同時引入另一個控件的使用,歡迎關注!

示例源碼


我在GitHub上建立了一個Repository,用來存放整個Android Material Design系列控件的學習案例,會伴隨著文章逐漸更新完善,歡迎大家補充交流,Star地址:

https://github.com/Mike-bel/MDStudySamples

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,734評論 25 708
  • 內容抽屜菜單ListViewWebViewSwitchButton按鈕點贊按鈕進度條TabLayout圖標下拉刷新...
    皇小弟閱讀 46,865評論 22 665
  • CoordinatorLayout與滾動的處理 CoordinatorLayout實現了多種Material De...
    cxm11閱讀 6,613評論 1 15
  • (文/習酒鎮?趙半仙) 樹葉被施了定身法 停在空中不說話 月亮撇撇嘴 俯視著人間的燈光 有點刺眼睛 星星啊 又偷懶...
    2632385d067a閱讀 431評論 3 14
  • 如果二婚和小孩只能選一個, 當然選小孩,小孩是專屬資產,老婆是共享資產, 小孩是一種儲蓄,老婆是一種消費, 老婆是...
    陳穩閱讀 152評論 0 0