Android Design Support Library 的 代碼實驗——幾行代碼,讓你的 APP 變得花俏

譯者地址:【翻】Android Design Support Library 的 代碼實驗——幾行代碼,讓你的 APP 變得花俏

原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session----Make your app fancy with few lines of code

原文項目 demo: Lab-Android-DesignLibrary

雙語對照地址: 【翻-雙語】Android Design Support Library 的 代碼實驗——幾行代碼,讓你的 APP 變得花俏

  • 翻譯: MrFu
  • 校驗: MrFu
  • 能去這里小小的點一下 star 嗎?非常感謝:Codelab
  • </ul> </blockquote>

    目前,我相信,沒有任何 Android 開發者不知道材料設計的,因為它的設計在過去的一年震驚了世界,正式的變成了一個設計理念。

    令人驚訝的是,在 Android 應用中材料設計是不容易實現的,因為材料設計的 UI 組件 如: Floating Action Button (FAB) 在低于 Android L 系統上是不可用的。我們只能選擇使用由獨立開發者公布出來的第三方庫。

    來了一個好消息,上周(2015.5.29)在谷歌2015 I/O 大會時,谷歌宣布了一個今年最讓人興奮的支持庫,名叫 Android Design Support Library,在這個單獨的 library 里提供了一堆有用的材料設計 UI 組件。通過這篇文章,讓我用這個機會向你一個一個描述如何來使用他們。

    請查看下面這個視頻作為本教程最終的結果。



    0
    </div>

    從這里開始,空白 Activity 里面有一個 DrawerLayout 。



    1
    </div>

    Activity 已經調整為材料設計風格的主題。

    <item name="colorPrimary">#2196F3</item>
    <item name="colorPrimaryDark">#1565C0</item>
    <item name="colorAccent">#E91E63</item>

    好了,讓我們開始吧!

    步驟一:從 Github 上拷貝源碼

    我已經為這個 codelab 準備了源碼,你可以從 GitHub 輕松的 clone 它。MainActivity 是上面所示的最終結果。請在這個 project 的CodeLabActivity中做我們的代碼實驗。

    你一定要自己做的一個任務是... 成功的運行它,它應該是通過簡單的點擊“運行”按鈕來完成。

    步驟二:添加 Android Design Support Library 依賴

    第一件要做的事是在我們的項目中添加 Android Design Support Library,在 app 的build.gradle文件下添加一行依賴代碼。

    compile 'com.android.support:design:22.2.0'

    `
    請注意 Design Support Library 依賴于 Support v4 和 AppCompat v7。一旦你在你的項目中添加這個 library,你也將獲得一個這些 libraries 的組件的入口。(譯者注:就是說 Design Support Library 中就已經包含了 Support v4 和 AppCompat v7)

    順便說一下,從 Github 克隆的源碼已經添加了上面這行代碼。但是如果你創建了你自己的項目,你需要自己添加它。

    步驟三:添加 FAB

    Floating Action Button (FAB) 是一個有一些陰影的圓形按鈕,這個令人難以置信的,可以改變世界的設計。毫不奇怪它為什么會變成材料設計的標志。因此我們從這開始。添加一個 FAB 在布局文件,因為它需要一些父類來使它在屏幕的右下方位置對齊,所以用FrameLayout來包裹FloatingActionButton。請做這樣的事情作為 DrawerLayout 的內容:更換activity_code_lab.xml中已經存在的TextView,像下面的代碼這樣。

    <android.support.v4.widget.DrawerLayout ...
        xmlns:app="http://schemas.android.com/apk/res-auto"
        ....>
        <FrameLayout
            android:id="@+id/rootLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <android.support.design.widget.FloatingActionButton
                android:id="@+id/fabBtn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|right"
                android:src="@drawable/ic_plus"
                app:fabSize="normal" />
        </FrameLayout>
        ...
    </android.support.v4.widget.DrawerLayout>

    android:src是用來定義你想要的資源文件 ID(推薦 40dp 的清晰的 png 文件),而app:fabSize="normal"是用來定義 FAB 的大小的,normal的意思是在大多數情況下標準尺寸為 56dp 的按鈕,但是萬一你想使用較小的一個,mini是另一個選擇,它的大小將變成 40dp。

    就這樣,FAB 現在準備使用!下面是當我在 Android 4.4 上運行這段代碼的結果。



    p0
    </div>

    但是當我們運行在 Android 5.0 上時,結果變成了這樣...



    p1
    </div>

    這不是特效,只是一個 bug。幸運的是 design library 的開發者團隊已經知道這個問題并在不久的將來會發布一個修復的版本。但是如果你現在想要使用它,我們可以做一些事情:通過設置 FAB 的 margin right 和 margin bottom 為 16dp 在 API Level 21+ 上面并在 低于 Android L 的版本上 設置為 0dp。感謝配置資源可以讓我們非常容易的做到這一點。

    res/values/dimens.xml

    <dimen name="codelab_fab_margin_right">0dp</dimen>
    <dimen name="codelab_fab_margin_bottom">0dp</dimen>

    res/values-v21/dimens.xml

    <dimen name="codelab_fab_margin_right">16dp</dimen>
    <dimen name="codelab_fab_margin_bottom">16dp</dimen>

    res/layout/activity_code_lab.xml

    <android.support.design.widget.FloatingActionButton
        ...
        android:layout_marginBottom="@dimen/codelab_fab_margin_bottom"
        android:layout_marginRight="@dimen/codelab_fab_margin_right"
        .../>

    好了!



    p2
    </div>

    這里有另一個 bug。陰影,你在哪里?這個 bug 和先前的那個是有關聯的。你可以通過定義app:borderWidth="0"作為 FAB 的屬性 作為一個快速的解決方案。



    p3
    </div>

    歡迎回來,陰影!其深度是自動設置的最佳實踐之一:6dp 在空閑狀態,12dp 是按下狀態。反正你可以通過定義重寫這些值,app:elevation為空閑狀態下的陰影深度,andapp:pressedTranslationZ為按下狀態的。

    關于按鈕的顏色,FAB 基本上使用強調色,但是你可以重寫app:backgroundTint屬性來修改。

    就像傳統的按鈕,你可以通過setOnClickListener()處理點擊,在CodeLabActivity.java文件的initInstances方法中添加下面的代碼。

    FloatingActionButton fabBtn;
    ...
    private void initInstances() {
        ...
        fabBtn = (FloatingActionButton) findViewById(R.id.fabBtn);
        fabBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });
    }

    完成!

    步驟四:使用 Snackbar

    Snackbar,在屏幕的地步一個微小的黑色條顯示著一條簡短的消息,在這個 library 中也是可用的。Snackbar 和 Toast 有著相同的概念,但是不同于 Toast,它的表現是作為 UI 的一部分而不是覆蓋在屏幕上。



    p4
    </div>

    不只是概念相同,編碼風格也是由 Toast 所啟發,你可以通過下面的代碼喚起 Snackbar。

    Snackbar.make(someView, "Hello. I am Snackbar!", Snackbar.LENGTH_SHORT)
            .setAction("Undo", new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                }
            })
            .show();

    make()的第一個參數是一個 View 或者 Layout,你想在它的底部位置顯示一個 Snackbar。在這個例子中,一個 FrameLayout 包裹著一個 FAB 就是其中一個例子。setAction()方法是用在設置動作顯示在 Snackbar 的右側并有對應的監聽。這個方法不是必需的,可以移除。

    現在,讓我們通過添加下面的代碼去試試。

    FrameLayout rootLayout;
    ...
    private void initInstances() {
        ...
        rootLayout = (FrameLayout) findViewById(R.id.rootLayout);
        fabBtn = (FloatingActionButton) findViewById(R.id.fabBtn);
        fabBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(rootLayout, "Hello. I am Snackbar!", Snackbar.LENGTH_SHORT)
                        .setAction("Undo", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                            }
                        })
                        .show();
            }
        });
    }

    點擊 FAB 以及看到的結果。



    p5
    </div>

    有用!但是... 還不是很完美。它是出現在放置 Snackbar 頂部的位置,長期的用戶體驗是很差的。不管怎么樣,這個行為已經是正確的,因為這里沒有為 Snackbar 和 FAB 定義任何關聯。

    為了這個目的專門發明了一個特殊的布局,使子 Views 協調工作。這就不用奇怪為什么它的名字是CoordinatorLayout了。

    步驟五:使他們和 CoordinatorLayout 協作

    CoordinatorLayout 是一個讓子 Views 協調工作的布局。這里沒有任何魔法。每個 View 中肯定是設計和實現了和 CoordinatorLayout 協同工作的。FAB 和 Snackbar 就是這兩個view。

    所以... 現在讓我們將 FrameLayout 改成CoordinatorLayout包裹一個FAB。

    res/layout/activity_code_lab.xml

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/rootLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.design.widget.FloatingActionButton
            ... />
    </android.support.design.widget.CoordinatorLayout>

    而且,不要忘了在CodeLabActivity.java改變 rootLayout 的變量類型為 CoordinatorLayout,否則就會崩潰。

    //FrameLayout rootLayout;
    CoordinatorLayout rootLayout;
    //rootLayout = (FrameLayout) findViewById(R.id.rootLayout);
    rootLayout = (CoordinatorLayout) findViewById(R.id.rootLayout);

    結果:現在 FAB 隨著 Snackbar 的出現和消失而移動。還增加了一些功能。Snackbar 現在能夠滑動消失了!請試一試。



    2
    </div>

    但是 bug 到處都是… bug 出現在低于 Android L 的系統上,當 Snackbar 滑動消失的時候,FAB 忘記了移動下來。



    3
    </div>

    這顯然是一個 bug,但是我不知道確切的原因。感謝天主,這里有一些解決方法。從我的實驗中,我發現當我們設置 FAB 的 margin bottom 和 margin right 為一些非零的正數值時,它將會奇跡般的正常工作,所以..就只需要為低于 Android L 的系統改變 margin 的值為 0.1dp就行。

    res/values/dimens.xml

    <dimen name="codelab_fab_margin_right">0.1dp</dimen>
    <dimen name="codelab_fab_margin_bottom">0.1dp</dimen>

    完成。下面是結果。



    4
    </div>

    從現在起,如果你計劃使用 Android Design Support Library。請首先考慮 CoordinatorLayout,因為它就像是這個 library 的核心。

    步驟六:再見 ActionBar,你好,Toolbar

    Toolbar 不是 Android Design Support Library 的一部分,而是在這個庫中需要與其他組件一起使用。

    Toolbar 是一個替代傳統的 Action Bar 具有更靈活的行為。我鼓勵你們從現在開始隱藏 Action Bar 并且切換到 Toolbar。因為這些有奇妙功能的新庫,包括 Design Support Library 的組件中,都被設計為和 Toolbar 協同工作而不是 Action Bar。

    很容易切換到 Toolbar。只需要從 Activity 定義的 AppTheme 的 style 屬性隱藏掉 Action Bar 開始。

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    然后在 CoordinatorLayout 里面的 FAB 之前正確的放一個 Toolbar 組件。

    <android.support.design.widget.CoordinatorLayout
        ...>
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
        <android.support.design.widget.FloatingActionButton
            ...>
        </android.support.design.widget.FloatingActionButton>
    </android.support.design.widget.CoordinatorLayout>

    現在寫代碼來告訴系統,我們將使用 Toolbar 作為一個 Action Bar,更換下面的 Java 代碼。

    Toolbar toolbar;
    private void initInstances() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ...
    }

    雖然它現在可以運行成功,但是根據我之前說的,放在 CoordinatorLayout 的東西必須被設計和實現成與它一起合作的,否則將不與任何其他兄弟 views(sibling views) 協作。但是... Toolbar是不合適的。別擔心,這里沒有任何新的特殊 Toolbar。只是一個組件是為了準備讓 Toolbar 與 CoordinatorLayout 一起工作的更加完美。這是簡單的任務,只是簡單的用AppBarLayout包裹 Toolbar,就這樣!

    <android.support.design.widget.CoordinatorLayout
        ...>
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
           <android.support.v7.widget.Toolbar
               .../>
        </android.support.design.widget.AppBarLayout>
        <android.support.design.widget.FloatingActionButton
            ...>
        </android.support.design.widget.FloatingActionButton>
    </android.support.design.widget.CoordinatorLayout>

    現在運行和測試,如果你做的都是對的,你將會看到 Drawer Menu 會覆蓋在 App Bar區域的頂部。使用了 AppBarLayout 的輸出結果是:低于應用欄區域的陰影現在回來了,耶!(譯者注:不曉得怎么翻了:The outgrowth of applying AppBarLayout is the drop shadow below App Bar area is now returned ! Yah !)



    5
    </div>

    這個步驟現在完成了。從現在開始,我建議你總是用 AppBarLayout 包裹 ToolBar 元素。光憑它能帶回來陰影的能力就足夠有說服力。

    步驟7:在內容區域放東西

    我們已經得到了 FAB 和 Toolbar,現在是時候在 Activity 的內容區域放上東西了。

    額。如果是兩個簡單的按鈕呢?好吧,讓我們把它們放在在 AppBarLayout 和 FAB 之間。

        ...
    </android.support.design.widget.AppBarLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Yo Yo"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Yo Yo"/>
    </LinearLayout>
    <android.support.design.widget.FloatingActionButton
        ...>

    下面是結果...



    p6
    </div>

    這些按鈕似乎都出人意料的放在了 Toolbar 下面。猜猜為什么?

    是的,一些古老的原因,LinearLayout 沒有被設計成與 CoordinatorLayout 協同工作。在這樣的情況下,沒有任何布局用來包裹 LinearLayout,使它像 Toolbar 的做法那樣。但它是更加容易的,你只需要在 LinearLayout 添加一個屬性告訴它的滾動行為,就像下面寫的這樣:

    <LinearLayout
        ...
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        ...>

    現在,他們被放在了正確的位置了,耶!



    p7
    </div>

    完成!=)

    步驟8:玩轉 TabLayout

    Tab 是在 Android 應用程序中用戶體驗(UX)最佳實踐的一部分。在以前,如果我們想要使用新的材料設計風格的 Tab,我們需要自己去為項目中下載 SlidingTabLayout 和 SlidingTabStrip 的源碼。現在,我們只需要使用這個庫提供的TabLayout,它也有很多可以調整的選項。

    我們應該把 TabLayout 放在哪里?根據 Android 應用程序用戶體驗指導原則,Tab 應該放在屏幕的頂部而不是在底部。還有,它應該在陰影部分的上面。所以,我們將其放在 AppBarLayout 里面,沿著 Toolbar。這是可以做到的,因為 AppBarLayout 是繼承自一個垂直的 LinearLayout

    <android.support.design.widget.AppBarLayout ...>
        <android.support.v7.widget.Toolbar ... />
        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </android.support.design.widget.AppBarLayout>

    在 Java 代碼中添加一些 tabs。

    TabLayout tabLayout;
    private void initInstances() {
        tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
        ...
    }

    下面是結果:



    p8
    </div>

    背景色會自動設置成 primary color(主題色),而導航線的顏色是強調色。但是你將會注意到 Tab 的字體仍然是黑色的,但是我們希望字體是白色的。這是因為我們還沒有為 TabLayout 提供任何主題呢。TabLayout 定義主題是簡單的,就像這樣:

    <android.support.design.widget.TabLayout
        ...
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

    現在,他們是白色的了。



    p9
    </div>

    你可以像上面這樣選擇手動控制 TabLayout,或者讓它和 ViewPager 一起工作,自動調用setupWithViewPager(...)。我相信這種情況會很頻繁的使用。

    還有,我們可以調整兩個屬性來顯示 TabLayout。

    app:tabMode- 如果你想在屏幕上顯示出每個單獨的 tab,就設置 tab 為fixed的, 。它適合只有少數 tab 的時候,但是如果有很多的 tab 的時候這是一個完全錯誤的選擇。在這種情況下你是不確定所有的 tab 是否能很好的在同一時間顯示出來的。所以,你可以設置這個屬性為scrollable讓用戶去滾動 tab,就像 Google Play Store 那樣。

    app:tabGravity- 如果你想要分配所有的可用空間給每個 tab,就設置這個屬性為fill。如果你想要所有的 tab 在屏幕的中間,就設置這個屬性為center。請注意,如果 tabMode 是設置成 scrollable 的,則這個屬性將會被忽略。

    每個模式的樣子就像下面這樣:



    p10
    </div>

    TabLayout 完成了!

    步驟9:當隨著內容滾動時,讓 AppBarLayout 退出屏幕

    一個優美的 Android 用戶體驗是引導 App Bar 可以隨著內容滾動出屏幕的,以獲得額外的空間來顯示內容,并且,這已經是被證明這樣的用戶體驗是很棒的。以前有一些應用程序已經實現了這種行為,但是開發者必須自己來實現。現在它只需要用一行代碼就能輕松的完成。

    首先,我們需要讓內容能夠滾動,先往 LinearLayout 加入一些 Button。大約20個?

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Yo Yo"/>
    ...
    <!-- Add 20 more buttons here -->
    ...
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Yo Yo"/>

    然后用 ScrollView 包裹這個 LinearLayout,還有,不要忘了將 LinearLayout 里的 layout_behavior 移動到 ScrollView,因為現在 ScrollView 是 CoordinatorLayout的最直接的子 view。

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            ...
        </LinearLayout>
    </ScrollView>

    然后給 Toolbar 添加一個滾動標志,就像這樣:

    <android.support.v7.widget.Toolbar
        ...
        app:layout_scrollFlags="scroll|enterAlways" />

    試試吧



    6
    </div>

    額... 原先假定的 Toolbar 會隨著內容的滾動滾出屏幕的,但是為什么它看起來什么都沒有實現呢?

    同樣的老原因啦... ScrollView 沒有被設計成與 CoordinatorLayout 協同工作(又來)。你需要另一個 view:NestedScrollView,Android Support Library v4 中有提供。這個 NestedScrollView 設計出來的目的就是為了與 CoordinatorLayout 協同工作的。

    <android.support.v4.widget.NestedScrollView ...>
        <LinearLayout ...>
            ...
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>

    同樣的原因,請注意了: ListView 類也是和 CoordinatorLayout 不能協同工作的。只有RecyclerView可以。也許需要時間來改變咯~

    這里將 ScrollView 改變成 NestedScrollView 后的結果。



    7
    </div>

    運行起來真贊!你會注意到 Toolbar 滾出了屏幕,但是 TabLayout 仍然還在。這是因為我們沒有給 TabLayout 設置任何滾動標志。如果你想要 TabLayout 同樣從屏幕上消失,只需要給 TabLayout 定義相同的屬性就可以了。

    <android.support.design.widget.TabLayout
        ...
        app:layout_scrollFlags="scroll|enterAlways" />

    結果:



    8
    </div>

    這里會有一些手勢上的 bug。我發現拉它回到屏幕是非常困難的。看來我們得等下一個版本了。

    現在,讓我們來看看它的一些細節。很好奇這些標志的真實意思是什么:scroll和enterAlways?事實上我們可以在這里設置4個屬性值。

    scroll- 你想你想要設置這個 view 隨著內容滾動,你需要應用這個標志。

    enterAlwaysCollapsed- 這個標志定義了 View 是如何回到屏幕的。當你的 view 已經聲明了一個最小高度(minHeight) 并且你使用了這個標志,你的 View 只有在回到這個最小的高度的時候才會展開,只有當 view 已經到達頂部之后它才會重新展開全部高度。滾動標志像這樣來使用它:scroll|enterAlwaysCollapsed。



    9
    </div>

    它好像在這個 minHeight 部分死活不工作。這里和 TabLayout 有另一個問題。很難把這些 View 拉回到屏幕來。

    enterAlways- 這個標志確保了任何向下滾動的操作都會讓這個 view 變得可見,達到“快速返回”(‘quick return’ )的效果,滾動標志像這樣來使用它:scroll|enterAlways



    10
    </div>

    exitUntilCollapsed- View 將關閉滾動直到它被折疊起來(有 minHeight) 并且一直保持這樣,舉個例子:

    <android.support.v7.widget.Toolbar
        ...
        android:layout_height="192dp"
        android:gravity="bottom"
        android:paddingBottom="12dp"
        android:minHeight="?attr/actionBarSize"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"/>

    下面是上述代碼的結果:



    11
    </div>

    這種模式在組件中經常使用,我將在下一個部分討論。

    步驟10: 移除 TabLayout

    從實驗來看,在上述情況下當我們用 TabLayout 來滾動的時候,有一些明顯的 bug。我相信這只是一個 bug,而且以后會被修復的。現在,讓我們首先從代碼中移除 TabLayout,確保下一步運行是流暢的。

    <!--android.support.design.widget.TabLayout -->

    從 Java 代碼中也刪除

    //tabLayout = (TabLayout) findViewById(R.id.tabLayout);
    //tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
    //tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
    //tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));

    好了,讓我們去做下一步!

    Step 11: Make Toolbar collapsable 步驟11:使工具欄可折疊

    就像在 exitUntilCollapsed 部分所示的例子中,Toolbar 可以展開和折疊,但是你會看到它還不是很完美。Toolbar 仍然離開了屏幕,最好的體驗是讓這些 icon (漢堡等-即菜單欄) 應該留在屏幕內。

    Design Support Library 已經為這個準備好了。用CollapsingToolbarLayout你可以像魔術一樣讓 Toolbar 折疊起來,就像其他組件一樣,它是非常容易使用的,具體操作步驟如下:

    • 用CollapsingToolbarLayout包裹Toolbar,但仍然在AppBarLayout中

      </li>

    • 從Toolbar中刪除layout_scrollFlags

      </li>

    • 為CollapsingToolbarLayout聲明layout_scrollFlags,并且將layout_scrollFlags設置成scroll|exitUntilCollapsed

      </li>

    • 改變 AppBarLayout 擴張狀態時的布局高度大小。在這個例子中,我用 256dp
    • </ul>

      這是最終代碼。

      <android.support.design.widget.AppBarLayout
          android:layout_width="match_parent"
          android:layout_height="256dp">
          <android.support.design.widget.CollapsingToolbarLayout
              android:id="@+id/collapsingToolbarLayout"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              app:layout_scrollFlags="scroll|exitUntilCollapsed">
              <android.support.v7.widget.Toolbar
                  android:id="@+id/toolbar"
                  android:layout_width="match_parent"
                  android:layout_height="?attr/actionBarSize"
                  android:background="?attr/colorPrimary"
                  android:minHeight="?attr/actionBarSize"
                  app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                  app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
          </android.support.design.widget.CollapsingToolbarLayout>
      </android.support.design.widget.AppBarLayout>

      這個結果是:



      12
      </div>

      看起來不錯,但是這些 Toolbar icons 仍然滾出了屏幕。我們可以聲明這個屬性給 Toolbar 來固定住它,讓它總是在屏幕的頂部。

      <android.support.v7.widget.Toolbar
          ...
          app:layout_collapseMode="pin"/>

      Toolbar現在被定住了!



      13
      </div>

      但是,等一下…標題的文字在哪里?!不幸的是,在用 CollapsingToolbarLayout 包裹住 Toolbar 后,它隨風而逝了。我們必須通過在 Java 代碼中手動設置setTitle(String)來實現。

      CollapsingToolbarLayout collapsingToolbarLayout;
      private void initInstances() {
          ...
          collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsingToolbarLayout);
          collapsingToolbarLayout.setTitle("Design Library");
      }

      結果:



      14
      </div>

      這里的字體顏色仍然是黑的的。這是因為我們還沒有為 App Ba 設置任何主題。要做到這一點,只需要簡單的為AppBarLayout聲明android:theme屬性就可以了,就像這樣:

      <android.support.design.widget.AppBarLayout
          ...
          android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

      現在,標題變成了白色的了!



      15
      </div>

      由于CollapsingToolbarLayout 的 特點,應用的標題文字在收縮和展開狀態是會自動過渡的。如果你想要在展開狀態改變標題文字的位置,你可以這樣做:通過應用的 margin 的4個屬性,就是:app:expandedTitleMargin,app:expandedTitleMarginBottom,app:expandedTitleMarginEnd以及app:expandedTitleMarginStart

      或者如果你想要在折疊和展開狀態時改變文本的顯示。你可以這樣來簡單的實現:設置 TextAppearance,分別通過app:collapsedTitleTextAppearance和app:expandedTitleTextAppearance來設置。

      讓我們從試著改變 margin 為64dp 開始。

      <android.support.design.widget.CollapsingToolbarLayout
          ...
          app:expandedTitleMarginStart="64dp">

      結果:



      16
      </div>

      真棒!

      步驟12:為 App Bar 添加背景圖片

      在這種情況下,我們想要用一張美麗的圖片作為 App Bar 的背景,而不只是像現在這樣的一個普通的顏色。幸運的是 CollapsingToolbarLayout 是繼承自 FrameLayout 所以我們可以輕松的添加一個 ImageView 作為 Toolbar 的背景圖層,就像這樣:

      <ImageView
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:scaleType="centerCrop"
          android:src="@drawable/header" />
      <android.support.v7.widget.Toolbar
          ...

      結果:



      17
      </div>

      圖片已經顯示出來了,但是這里有一點還沒有達到預期,藍色的導航條仍舊顯示著。有一個 Toolbar 的背景看起來不是酷炫的。從 Toolbar 移除它,只需要下面這行代碼就行了。

      android:background="?attr/colorPrimary"

      結果:



      18
      </div>

      現在圖片是隨著內容的滾動了,但是看起來太呆了。我們可以使用視差模式讓它變得更優雅一些,只需要聲明 collapse 就行了,像下面這樣:

      <ImageView
         ...
         app:layout_collapseMode="parallax" />

      結果:



      19
      </div>

      你也可以設置視差的系數,介于 0.0-1.0之間。

      app:layout_collapseParallaxMultiplier="0.7"

      請你自己去嘗試一下=)

      最后你可能會注意到 App Bar 的背景總顯示一張圖片。你可以讓它在收縮的時候自動的變化到普通的顏色,通過聲明屬性 app:contentScrim 像下面這樣來實現:

      <android.support.design.widget.CollapsingToolbarLayout
          ...
          app:contentScrim="?attr/colorPrimary">

      結果:



      20
      </div>

      只用了幾行代碼,就讓 App Bar 變得這么漂亮了 =)

      步驟13:玩轉 Navigation Drawer

      現在從左側拉出 Drawer Menu 仍然只是一個空白的面板。在以前,實現這個菜單是非常麻煩的,因為我們不得不手動的用 LinearLayout 或者 ListView 去實現。

      在 Android Design Support Library 中提供了 NavigationView,實現它變得更容易了,它為我們節省了15.84321倍的時間!

      首先,為 Drawer Menu 創建一個標題視頻布局文件。(它已經在 Github的項目中了)

      res/layout/nav_header.xml

      <?xml version="1.0" encoding="utf-8"?>
      <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="192dp"
          android:theme="@style/ThemeOverlay.AppCompat.Dark">
          <ImageView
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:src="@drawable/nav_header_bg"
              android:scaleType="centerCrop" />
          <ImageView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:src="@drawable/nuuneoi"
              android:layout_gravity="bottom"
              android:layout_marginBottom="36dp" />
          <TextView
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_gravity="bottom"
              android:layout_margin="16dp"
              android:text="nuuneoi"
              android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
      </FrameLayout>

      現在創建一個菜單資源文件

      res/menu/navigation_drawer_items.xml

      <?xml version="1.0" encoding="utf-8"?>
      <menu xmlns:android="http://schemas.android.com/apk/res/android">
          <group android:checkableBehavior="all">
              <item
                  android:id="@+id/navItem1"
                  android:icon="@drawable/ic_action_location_found_dark"
                  android:title="Home"/>
              <item
                  android:id="@+id/navItem2"
                  android:icon="@drawable/ic_action_location_found_dark"
                  android:title="Blog"/>
              <item
                  android:id="@+id/navItem3"
                  android:icon="@drawable/ic_action_location_found_dark"
                  android:title="About"/>
              <item
                  android:id="@+id/navItem4"
                  android:icon="@drawable/ic_action_location_found_dark"
                  android:title="Contact"/>
          </group>
      </menu>

      NavigationView與兩個資源文件綁定起來,作為 Drawer Menu 的菜單區域,用下面的代碼來替換一個已經存在的 白色的 LinearLayout :

              ...
          </android.support.design.widget.CoordinatorLayout>
          <android.support.design.widget.NavigationView
              android:id="@+id/navigation"
              android:layout_width="wrap_content"
              android:layout_height="match_parent"
              android:layout_gravity="start"
              app:headerLayout="@layout/nav_header"
              app:itemIconTint="#333"
              app:itemTextColor="#333"
              app:menu="@menu/navigation_drawer_items" />
      </android.support.v4.widget.DrawerLayout>

      現在:召喚 Drawer Menu!哇喔,哇喔



      21
      </div>

      NavigationView 就是為了 Drawer Menu 而特別設計的。所以,所有的東西都會被創建并且自動測量包括菜單的寬度等,我們自己定義案例來配置以前的設計。

      為了處理這些菜單項的點擊事件,你可以聲明setNavigationItemSelectedListener來監聽,就像下面這樣:

      NavigationView navigation;
      private void initInstances() {
          ...
          navigation = (NavigationView) findViewById(R.id.navigation);
          navigation.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
              @Override
              public boolean onNavigationItemSelected(MenuItem menuItem) {
                  int id = menuItem.getItemId();
                  switch (id) {
                      case R.id.navItem1:
                          break;
                      case R.id.navItem2:
                          break;
                      case R.id.navItem3:
                          break;
                  }
                  return false;
              }
          });
      }

      在實際使用中,請隨意的區聲明你想要定義的 header view 和修改菜單項。

      步驟14:用上 TextInputLayout 讓 EditText 變的更風騷

      這是 Codelab 的最后一部分了。你可以改變一個舊的 EditText 的風格,讓它變得更時髦,即:總是會顯示一個提示或者一個錯誤信息。

      要做到這一點,只需要簡單的用 TextInputLayout 包裹住一個 EditText ,就這么簡單!

      <android.support.design.widget.TextInputLayout
          android:layout_width="match_parent"
          android:layout_height="wrap_content">
          <EditText
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:hint="Username" />
      </android.support.design.widget.TextInputLayout>

      把這兩個控件放到 NestedScrollView 里看下結果。



      22
      </div>

      難以置信的容易吧?=)

      結論

      Android Design Support Library 是非常有前途的支持庫,它非常值得在你的產品上使用。雖然它仍然包含了很多錯誤,我建議你再等等,直到每個錯誤都被修復。

      這么長的教程,希望希望你覺得它有用 =)

      `


      p11
      </div>
      Author: nuuneoi (Android GDE, CTO & CEO at The Cheese Factory)
      A full-stack developer with more than 6 years experience on Android Application Development and more than 12 years in Mobile Application Development industry. Also has skill in Infrastucture, Service Side, Design, UI&UX, Hardware, Optimization, Cooking, Photographing, Blogging, Training, Public Speaking and do love to share things to people in the world!

       本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
       轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
       本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!