今年(2014) 的 Google I/O 發表令多數人為之一亮的 Material Design,而 Google 也從「Google I/O 2014」 開始,大家也陸陸續續地看到其更新的 Android APP 皆套用了這個設計介面。當然,這個設計介面著實讓大家感到驚艷外,更讓 Android 開發者開始擔心未來 APP 的介面處理了。
不過,所幸有著之前 ActionBar 的經驗後,Android 也很快地在 support library 裡面提供了相對應的 API 給開發者使用,本篇就為各位介紹 – Toolbar,這是用來取代過去 ActionBar 的元件,而現在於 material design 中也對之有一個統一名稱:App bar,在未來的 android app 中,就以 Toolbar 這個元件來實作之。
1. 概述
在 Android 3.0 開始 Android 推了 ActionBar 這個介面出來,而到了 2013 年 Google 開始大力地推動所謂的 android style,想要逐漸改善過去 android 紛亂的介面設計,希望讓終端使用者盡可能在 android 手機有個一致的操作體驗。ActionBar 過去最多人使用的兩大套件就是 ActionBarSherlock 以及官方提供在 support library v7 裡的 AppCompat 中。
既然會有本篇可以跟各位介紹的 Toolbar,也意謂著官方在某些程度上認為 ActionBar 限制了 android app 的開發與設計的彈性,而在 material design 也對之做了名稱的定義:App bar。接下來將為各位分成幾個階段進行說明,如何在 android app app 中用 toolbar 這個元件來做出一個基本的 app bar 嘍。
本篇所使用到的程式碼:toolbar demo check point 0 ~ 4,請到 Github 取得。
2. 基礎套用
這個階段從 toolbar_demo_checkpoint0 開始,分成下列三個部份:
- 風格 (style)
- 介面 (layout)
- 程式 (java)
2.1 風格(style)
風格要調整的地方有二,一在 res/values/styles.xml 另一在 /res/values-v21/styles.xml,為了之後設定方便,我們先在 res/values/styles.xml 裡增加一個名為 AppTheme.Base 的風格
1 2 3 4 5 6 |
<style name="AppTheme.Base" parent="Theme.AppCompat"> <item name="windowActionBar">false</item> <del><item name="android:windowNoTitle">true</item></del> <!-- 使用 API Level 22 編譯的話,要拿掉前綴字 --> <item name="windowNoTitle">true</item> </style> |
因為此範例只單純使用 Toolbar,所以我們要將讓原本的 ActionBar 隱藏起來,做了上面的設定,接著將原本 AppTheme 的 parent 屬性 改為 AppTheme.Base,這邊完整的程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="AppTheme.Base"> </style> <style name="AppTheme.Base" parent="Theme.AppCompat"> <item name="windowActionBar">false</item> <del><item name="android:windowNoTitle">true</item></del> <!-- 使用 API Level 22 編譯的話,要拿掉前綴字 --> <item name="windowNoTitle">true</item> </style> </resources> |
再來調整在 Android 5 的風格檔: /res/values-v21/styles.xml,也將其 parent 屬性改為 AppTheme.Base:
1 2 3 4 5 |
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppTheme" parent="AppTheme.Base"> </style> </resources> |
2.2 介面(Layout)
在 activity_main.xml 裡面加入 Toolbar 元件:
1 2 3 4 5 6 |
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_height="?attr/actionBarSize" android:layout_width="match_parent" > </android.support.v7.widget.Toolbar> |
請記得用 support v7 裡的 toolbar,不然會只有 API Level 21 也就是 Android 5 以上的版本才能使用。
這邊需注意,要將 RelatvieLayout 裡的針對四個方向 padding 屬性拿掉,並記得將原本的 Hello World 設定 layout_below="@+id/toolbar" ,否則會看到像下面這樣的錯誤畫面。
2.3 程式 (Java)
請到 MainActivity.java 裡加入 Toolbar 的宣告:
1 2 |
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); |
宣告後,再將之用 setSupportActionBar 設定,即能取代表原本的 actionbar 嘍,此階段完成畫面如下:
完整程式碼請見:toolbar_demo_checkpoint1
3. 調色 (Customization color)
這個階段將從 toolbar_demo_checkpoint1 接著往下進行:
上圖是將本階段要完成的結果畫面做了標示,搭配下述希望讓大家可以一目瞭然。
- 狀態列底色:
colorPrimaryDark
在風格 (styles) 或是主題 (themes) 裡進行設定。 - App bar 底色
這個設定分為二,若您的 android app 仍是使用 actionbar 實作,則直接在風格 (styles) 或是主題 (themes) 裡進行設定 colorPrimary 參數即可;
可若是採用 toolbar 的話,則要在介面 (layout) 裡面設定 toolbar 元件的 background 屬性。 - 導航列底色:navigationBarColor
僅能設定在 API v21 也就是 Android 5 以後的版本,因此要將之設定在 res/values-v21/styles.xml 裡面。 - 主視窗底色:windowBackground
也因此在這個階段,我們需要設定的地方有三,一是主要風格檔 (res/values/styles.xml)
1 2 3 4 5 6 7 8 9 10 11 |
<style name="AppTheme.Base" parent="Theme.AppCompat"> <item name="windowActionBar">false</item> <item name="android:windowNoTitle">true</item> <!-- Actionbar color --> <item name="colorPrimary">@color/accent_material_dark</item> <!--Status bar color--> <item name="colorPrimaryDark">@color/accent_material_light</item> <!--Window color--> <item name="android:windowBackground">@color/dim_foreground_material_dark</item> </style> |
再來是 v21 的風格檔 (res/values-v21/styles.xml)
1 2 3 4 |
<style name="AppTheme" parent="AppTheme.Base"> <!--Navigation bar color--> <item name="android:navigationBarColor">@color/accent_material_light</item> </style> |
最後,就是為了本篇的主角 – Toolbar 的 background 進行設定。
1 2 3 4 5 6 7 |
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_height="?attr/actionBarSize" android:layout_width="match_parent" android:background="?attr/colorPrimary" > </android.support.v7.widget.Toolbar> |
在本範例中,toolbar 是設定來在 activity_main.xml,對其設定 background 屬性: android:background="?attr/colorPrimary" ,這樣就可以使之延用 Actionbar 的顏色設定嘍。
完整程式碼請見: toolbar_demo_checkpoint2
4. 元件 (component)
本階段將從 toolbar_demo_checkpoint2 接續,在還未於
<android.support.v7.widget.Toolbar/> 標籤中,自行添加元件的 toolbar 有幾個大家常用的元素可以使用,請先見下圖:
大抵來說,預設常用的幾個元素就如圖中所標示,接著就依序來說明之:
- setNavigationIcon
即設定 up button 的圖示,因應 Material 的介面,在 Toolbar 這裡的 up button 樣示也就有別於過去的 ActionBar 嘍。 - setLogo
APP 的圖示。 - setTitle
主標題。 - setSubtitle
副標題。 - setOnMenuItemClickListener
設定選單各按鈕的動作。
先來看到選單外的程式碼,於 MainActivity.java 撰寫如下的程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); // App Logo toolbar.setLogo(R.drawable.ic_launcher); // Title toolbar.setTitle("My Title"); // Sub Title toolbar.setSubtitle("Sub title"); setSupportActionBar(toolbar); // Navigation Icon 要設定在 setSupoortActionBar 才有作用 // 否則會出現 back button toolbar.setNavigationIcon(R.drawable.ab_android); |
這邊要留意的是 setNavigationIcon 需要撰寫於 setSupportActionBar 之後才會生效。
選單的部份,需要先於 res/menu/menu_main.xml 做選單項目的設定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<menu 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" tools:context=".MainActivity"> <item android:id="@+id/action_edit" android:title="@string/action_edit" android:orderInCategory="80" android:icon="@drawable/ab_edit" app:showAsAction="ifRoom" /> <item android:id="@+id/action_share" android:title="@string/action_edit" android:orderInCategory="90" android:icon="@drawable/ab_share" app:showAsAction="ifRoom" /> <item android:id="@+id/action_settings" android:title="@string/action_settings" android:orderInCategory="100" app:showAsAction="never"/> </menu> |
再來回到 MainActivity.java 加入 OnMenuItemClickListener 的監聽式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
private Toolbar.OnMenuItemClickListener onMenuItemClick = new Toolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { String msg = ""; switch (menuItem.getItemId()) { case R.id.action_edit: msg += "Click edit"; break; case R.id.action_share: msg += "Click share"; break; case R.id.action_settings: msg += "Click setting"; break; } if(!msg.equals("")) { Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } return true; } }; |
接監聴式 onMenuItemClick 設定給 toolbar
1 2 3 4 5 6 |
setSupportActionBar(toolbar); ... // Menu item click 的監聽事件一樣要設定在 setSupportActionBar 才有作用 toolbar.setOnMenuItemClickListener(onMenuItemClick); |
和 setNavigationIcon 一樣,需要將之設定在 setSupportActionBar 之後才有作用。以上完成程式碼並執行之,可以看到如下的操作畫面嘍。
完整程式碼請見:toolbar_demo_checkpoint3
5. 總結
在這樣的架構設計下,Toolbar 直接成了 Layout 中大家可以控制的元件,相對於過去的 Actionbar 來說,設計跟操控性大幅度地提升。
本篇以上說明中所使用到的完整程式碼:toolbar demo check point 0 ~ 4,請到 Github 取得。
最後再附上一個介面上常會被設定的風格屬性,請見下圖:
這邊就從上到下做個簡單的整理:
- colorPrimaryDark
- 狀態列背景色。
- 設定在 style 的屬性中。
- textColorPrimary
- App bar 上的標題與更多選單中的文字顏色。
- 設定在 style 的屬性中
- App bar 的背景色
- Actionbar 的背景色設定在 style 中的 colorPrimary。
- Toolbar 的背景色設定其 layout 檔中的 background 的屬性中。
- colorAccent
- 各控制元件(如:check box、switch 或是 radoi) 被勾選 (checked) 或是選定 (selected) 的顏色。
- 設定在 style 的屬性中
- colorControlNormal
- 各控制元件的預設顏色。
- 設定在 style 的屬性中
- windowBackground
- App 的背景色。
- 設定在 style 的屬性中
- navigationBarColor
- 導航列的背景色,但只能用在 API Level 21 (Android 5) 以上的版本
- 設定在 style 的屬性中
6. 補充
在官網的 Issue 中,有人提到這樣的問題,當今天設定 android:minHeight="?attr/actionBarSize" 時,在轉為橫向呈現時,Toolbar 的高度會更得很詭異。所以,將高度的設定 ?attr/actionBarSize 回歸到 height 去,
1 |
android:layout_height="?attr/actionBarSize" |
這樣的設定即可。而本篇的內容以及範例程式皆已如此更正,還請各位留意一下之後的寫法。
本部落格採用創用CC 姓名標示-非商業性-禁止改作 3.0 台灣 授權條款授權,如欲轉載請記得註明「莫希爾(Mosil) 手札」
超詳細的說明!!
剛好看到最後一段程式碼的最後一行少了一點點,
參考您於gitHub上的分享,該行應如下方?
toolbar.setOnMenuItemClickListener(onMenuItemClick);
miaShopgal
是的,就是將該 Listener 設定給 toolbar 哦 🙂
不好意思剛接觸android Dev
請問toolbar 右邊的menu有辦法像
actionBar的 android:uioption一樣
直接把menu放在下面嗎?
還是要怎麼做呢?
a0937901037
這個看看?
http://stackoverflow.com/a/27490705/1083128
用兩個toolbar XD
miaShopgal a0937901037
這的確是解法 XD
您好 謝謝你的一步一步的教學說明 對於material 入門有個範例可以跟著走
但我在5.0 (API level 21)以下的版本沒有辦法改變status bar, 我在stackoverflow找到的原因是因為 5.0 以下 Staus Bar是由OS來管理, App 沒有權限去改變狀態欄顏色。
我的建議是把 colorPrimaryDark 移到 v21 版的 styles 檔案中. 因為5.0之後才適用. thx 若有錯誤也請指正一下 🙂
yesimroy 謝謝您的回饋
您說的沒有錯,該屬性是在 v21 以上的版本才會有作用,
不過那個屬性是否放在 values-v21 是沒有關係的,除非您用的是 android:colorPrimaryDark 這個專屬於 v21 以上的屬性。
感謝您看得這麼詳細 ^_^