Android – Toolbar 上的 Navigation Drawer

在 Material Design 釋出後,Google 也開始陸續更新了 Google app 的介面,讓大家有個範例可以看。而過去大力推動的 actionbar 自然而然也成了眾開發者觀注的部份;其中的 up button 的設定在前一篇所介紹的 Toolbar 也已看到。這邊還未提到的一個部份是 material design 中有提到的人機互動效果,簡言之,就是讓使用者明顯地感受到在操作 app 時,可以獲得明顯的回應,從而得到豐富地操作體驗感;因此,在剛開始釋出的幾支 Google app 裡,大家一定都有留意到開啟 navigation drawer 時,up button 從選單圖示 (menu/hamburger icon) 旋轉成倒退圖示 (back icon) 的新效果了!

Toolbar Nav Drawer

先來看到效果:

相信大家也都會很好奇這個效果要如何實作,會不會很麻煩?所幸,這個效果,被放進 support v7 之中,我們只要拿來用即可。在本篇中將分下列幾個部份,來帶大家無痛地寫出這個效果來。

  1. 實作
  2. Material design guideline 定義的 Side Drawer
  3. 其他議題

本篇所使用到的程式碼,請到 Github 下載。

 


我們馬上就開始從 navdrawer_deom_checkpoint0 開始 (這份程式碼其實就是在  Toolbar Step By Step – 調色 階段完成的 toolbar_demo_checkpoint2),

在 activity_main.xml 中加入 DrawerLayout

加入後,請記得將原本在 Toolbar 元件之前的 TextView 放到 <!-- Content -->  部份,做 DrawerLayout 其中的內容介面,否則在忘記放入 Content 介面的狀況下,關閉側邊欄時,會發生「java.lang.NullPointerException: Attempt to invoke virtual method ‘android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()’ on a null object reference」這樣的錯誤訊息。

drawer_view  中,要記得 layout_gravity 設定成 start  或是 left 。

activity_main.xml 完整程式碼請見 github。

再來,就是到 MainActivity.java 中去實作 DrawerLayout,部份程式碼如下:

完成後,就可以看到如上方影像一樣的效果了!

完整程式碼請見:navdrawer_demo_checkpoint1

 

2. Side Drawer


Material Design 導覽文件釋出之初,其實是沒有看到側邊欄的相關說明,一直到 2014.10 才以「Side Nav」之名,加述於導覽文件之中。而這個定義中的 Side Nav 畫面,其實跟原本在 actionbar 的階段是不太一樣的,drawer layout 會壓在 toolbar 上,如下圖:

NavDrawer over toolbar目前在 Google app 的介面中,還是以前一種為多,而現下 (2014.10) 如同 material  design 在 side nav 呈現的介面還不多。

接下來就用 navdrawer_demo_checkpoint1 做為這個階段的開始往下進行,需要調整就只有介面 (activity_main.xml) 的部份:

將 DrawerLayout 改到這個 layout 的 root 層,並將 toolbar 移到 content 的 layout 中,這樣就可以達到這樣的效果了。

需要注意的是地方在 Side 的 layout 要設定 clickable 的屬性設定為 true,否則會在側邊欄打開的狀況下,還能按到位於介面下方的 up button。

But!人生就是這個 but!

在前一陣子,Google 的設計師為 Google I/O 2014 設計了另外一種樣式出來,差異請見下圖:NavDrawer

嗯,簡言之,狀態列是半透明的狀態,而側邊欄可以被看到。要調整的地方有二,一在 layout – activity_main.xml:

在 root 層的 drawer layout 跟 side drawer 的 layout 各別加上 android:fitsSystemWindows="true" 這個屬性

另外一個要改的地方是在 v21/styles.xml

加入一個有透明度的色碼給 android:statusBarColor 這個狀態列顏色設定屬性。

這樣就可以完成這個階段的程式了。

完整程式碼請見:navdrawer_demo_checkpoint2

 

3. 其他議題


Navigation icon 切換的效果,除了旋轉以外,還有另外一種效果,請看下方的影像:

3.1 Navigation icon effect

左上角的切換效果變成線條的的聚合,同時 icon 的顏色也被改為黑色,這個設定只要在 /res/values/styles.xml 做如下設定

先加入針對 navigation icon 設定的風格: AppTheme.MyDrawerArrowStyle ,其繼承自 Widget.AppCompat.DrawerArrowToggle 這個風格。

以本範例來說,這個風格裡設定了兩個屬性:

  • spinBars
    • 旋轉效果
    • false。由此可之,其預設的旋轉效果預設值就是 true 了。
  • color
    • 設定 navigation icon 的顏色。

增加後,再回到 AppTheme.Base 風格中,將此風格設定給 drawerArrowStyle 即可看到效果了。

3.2 Shadows

在影像中,大家應該可以看到,這個範例中還有一處跟之前不同了,內容為 Hello world! 的 TextView 變成黑色了!哦!當然不是要為各位介紹這個以前就有屬性。要請各位留意的是在 TextView 周圍有一圈淡淡的影子,還有在 Toolbar 也因為下方的影子,看起來較有立體感。而這也就是在 Material design 中有提到的其中一個部份:Shadows

在過去這個效果需要自己去設定 drawable,現在只要設定個屬性即可。請到 activity_main.xml 中

最主要就是針對 android:elevation 這個屬性設定,而這個屬性的意義也如同其字面的意義,他是在承述相較於底層的高度而被創造出來的陰影。而另外,在這段程式碼中,特別將 TextView 中的 android:background 也列出來的原因,就是要讓大家知道,android:elevation 這個屬性要能夠生效,該介面元件的背景屬性也需要設定哦!

完整程式碼請見:navdrawer_demo_checkpoint3

 

4. 一點想法


新的 navigation drawer 在 material design 的 side nav 裡有著跟過去不同的樣式,而在 Google app 中,包含文中提到那種新的呈現樣式算來,共有三重風格。這應該也意謂著,以 Google 在 side nav 在 android app 的呈現上,給予了這些彈性在。換句話說,這樣看來,目前看到的這三種樣式在 android app 上來看,都可以算是 material design。

也許有人會問,那導覽文件是寫好玩的嗎?以個人的觀點來看,那個的確是一個規範,是 Google 想要在不同的平台上有一個共通的範疇得以依循。因此,相信未來在 Google 的產品中,於 web、iOS 以及其他裝置的介面,都會以 material design 做為標準,而設計出統一的 Google app 的體驗。

而在 android 裝置上,嘿嘿…畢竟是 Google 定義的嘛~那自然這部份的彈性就多於其他平台嘍。所以,私以為就別太過糾結於導覽文件上的定義,只要符合目前所看到的三種樣式,應該都可以被視 android 裝置上的 material design 啦。大家也可以放寬心的運用這三種樣式去做 android app 的設計嘍。

當然,以上純粹個人觀點,不代表官方立場,除非有 Google 的人在本篇中給予留言,做認證嘍 😛 

 

最後,附上本篇所有範例的程式連結,還請大家多多指教嘍。

 

2014/10/29 更新

剛巧,在同一天 Roman Nurik 在官方部落貼出了一篇 android app 的 material design 確認項目表,其中在 Navigation drawer 的部份也很明確的提到,drawer 就是以最新的釋出的樣式為標準,也就是 drawer 會覆蓋在 app bar 之上,被壓於 status bar 之下,最好還可以將 status bar 設定成半套明的樣子。

這樣的定義也有不少人問到,那這樣該 icon 都被蓋住了,要其動態效果何用?這個問題,Roman 在其 G+ 的貼文「Google I/O App Source Updated for Android 5.0 SDK」中做了如此的回應:「there are other situations where that animation can be used, e.g. moving from a top level section to a detail screen. More generally, I’d optimize for consistency and rational layering before optimizing for cool animations.」大抵的意思就是,該動畫還是會有地方可以被使用到,像是從上層 “移動” 到其下一層時。就算定義出很酷的動態效果,還是會以整體的層次感做為優先考量。

總歸來說,navigation drawer 的呈現,就是以下方這張由 Roman 定義好的樣式為標準啦!至於怎麼實作,還請往上看到實作說明嘍 =]


New drawer layering

至於為什麼有些有 navigation drawer 的 Google app 未遵從這樣的標準呢?忘了在哪一篇 G+ 裡面有看到,Roman 有回覆說,因為程式架構的關係還在調整,未來會朝這個標準來更新之。

 

 

本部落格採用創用CC 姓名標示-非商業性-禁止改作 3.0 台灣 授權條款授權,如欲轉載請記得註明「莫希爾(Mosil) 手札

Loading Facebook Comments ...

23 關於 “Android – Toolbar 上的 Navigation Drawer” 的評論

  1. 我有點不明白那個動畫的意義,
    如果根據官方文件,
    Side Drawer 是蓋在 Toolbar 上,

    如果不是像大大一樣特意把 Side Drawer 設定成透明,
    正常狀況下根本看不到那個動畫,
    然而新版的 Google Play 的 Side Drawer 卻仍然在 Toolbar 下,

    雖然這次 Material Design 讓人非常驚豔,
    但是感覺有很多東西根本都還沒確定…

  2. 可以請問如何正確的在ToolBar上加入SearchView嗎?
    目前嘗試過很多方法
    例如直接照官方actionbar的加法似乎可以,但searchview的部分無法輸入文字,也不曉得要怎麼擷取
    http://developer.android.com/training/search/setup.html

    這個blog似乎有些說明,但我看不是很懂
    http://android-developers.blogspot.tw/2014/10/appcompat-v21-material-design-for-pre.html

    這篇文章的searchview可以使用,但是他本身是actionbar,如果改成使用toolbar,app版本要v14以上,希望能夠向下支援v8
    http://www.edumobile.org/android/android-development/action-bar-search-view/

    希望能夠不吝指教,謝謝你

  3. Mosil 回報一下,我menu設定如同你連結的內容還是無法輸入文字,後來layout從你範例的https://github.com/mosil/Android-Mosil-Sample-NavDrawer/tree/master/navdrawer_demo_checkpoint2改成https://github.com/mosil/Android-Mosil-Sample-NavDrawer/tree/master/navdrawer_demo_checkpoint21的layout就可以輸入文字,目前卡在按下search鍵的時候沒有反應(沒有開啟另外一個activity),最後感謝你的回覆:)

  4. KevinStone
    要另開 activity 的話,得要另外寫哦。

    比方說,ServerView 是被寫在 SearchActivity 裡面;而原本的 activity 只是單純的放一個 search icon,然後對之進行動作判斷,再來就看您是使用 toolbar 或是 actionbar,在不同的地方寫下。

    若是 toolbar 的話,可以參考拙作 http://blog.mosil.biz/2014/10/android-toolbar/#component,將之寫在 onMenuItemClick 裡。
    若是 menu 的話,就是寫在 onOptionsItemSelected。

    之後,要執行搜尋的動作,就全部寫在 SearchActivity 裡面嘍。

    以上,希望對您有幫助 🙂

  5. KevinStone 您如果有想要做出類似 gmail 的那種呈現方法的話,這邊提出兩個想法給您參考:
    1. 用兩個 toolbar 去實作,點下跟取消的 listener 去將兩個 toolbar 切換
    2. 直接改變現有的 theme,然後再加入轉場的效果

  6. 你好,我是最近在你的G+上有發問的,關於程式碼的部份我放到google雲端硬碟,避免直接貼上變態混亂

    MainActivity – > https://docs.google.com/document/d/12l155d_P_vTvv0TwGe1YV8Dal-pUld5AHaZesfohUh8/edit?usp=sharing

    layout : activity_main.xml – > https://docs.google.com/document/d/1fpD7DTLJMWy5QP0_4hXqWgw-VvAxyl1NwAtKuki_ZSI/edit?usp=sharing

    非常感謝你

    程式碼的部分android studio 並沒有顯示錯誤

    只是layout無法顯示出模擬圖示

    主要是放上v7 那行 layout “android.support.v7.widget.Toolbar”

    會使他無法顯示,不知道問題出在哪呢?

    無法顯示的結圖連結 – > https://drive.google.com/file/d/0B3wjutlTIsSPOExxXzBnWUdVdEk/view?usp=sharing

  7. az56929 請問您有在 gradle 加上這個 library 嗎
    dependencies {

      compile ‘com.android.support:appcompat-v7:22.1.1’
      …
    }

  8. Mosil az56929 已經成功讓layout顯示出模擬圖了,謝謝

    不過程式會停止,這部分不知道能不能再請你幫忙..

    Error -> https://docs.google.com/document/d/1yLDA-q6OU-G-ZBNuEaoacd0DGqXmmnKrnfqtBnEUvaw/edit?usp=sharing

    上面是錯誤訊息

    而在 MainActivity.java 錯誤是24行  — > setSupportActionBar(toolbar);

    我之前是複製你  https://github.com/mosil/Android-Mosil-Sample-NavDrawer/tree/master/navdrawer_demo_checkpoint3

    出這錯誤我有改複製 https://github.com/mosil/Android-Mosil-Sample-NavDrawer/tree/master/navdrawer_demo_checkpoint30 的MainActivity 和layout

    錯誤訊息是相當類似的,而錯誤都是在 setSupportActionBar(toolbar);

    不知道這樣會不會有點亂,謝謝你的回覆

  9. Mosil az56929 不好意思,我沒注意到這篇,謝謝你的回覆,我試試看

    非常感謝你的幫忙~謝謝 🙂

  10. 我閱讀了你這篇的教學跟toolbar的教學,覺得這個方法比之前其他設計drawer的方法好用多了!!
    請問有Navigation Drawer(此篇方法)+ToolBar+Tab+ViewPager的教學嗎?
    假如是加上Tab是加在ToolBar上面還是要獨立出來呢?(比如像在ActionBar上可以加Tab)
    因為需要這種的介面
    可以指點一下嗎?還是有實際的範例文章可以參考呢?
    或是我該到哪裡尋求資源…
    拜託 感謝幫忙

  11. f2131772
    您的需求,以我自己的印象,好像沒有看到寫得清楚的文章。

    不過隨便找了一下,請看看這篇是否符合您的需求 

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *