Material Design 之 Toolbar 開發實踐總結

在2014年Google IO 大會上,Google 推出了一套全新的設計規范Material Design,這也為廣大的Android 開發者帶來了福音,不用像以前一樣照著IOS 視覺稿來開發Android APP,Material Design 的視覺風格本身就比較炫酷。請看Material Design 中文版,而Google 也為我們提供符合Material Design 風格的一系列組件,這大大的提高了我們的開發效率。由于APP改版在做Material Design 化,所以后面會結合項目中的使用情況寫幾篇關于Material Design 組件的文章。第一篇就從 Toolbar開始吧。

一、 認識Toolbar

官方原話:A Toolbar is a generalization of action bars
for use within application layouts. 意思就是 Toolbar 是應用內的action bars 的一個歸納。好像有點難懂,看不懂這句話沒關系,我們只要知道,Toolbar 使用來替代原來的ActionBar 的就行了。我們來看一下Toolbar的類繼承關系,如下圖:

toolbar_class.png

從繼承關系可以看出,繼承的是ViewGroup,也就是說Toolbar 是一個ViewGroup 容器,知道了這一點對于后面的理解就比較容易了。那么接下來我們看一下這個容器里面有些什么東西,還是看一下官方文檔:


toolbar.png

文檔說得很清楚,一個Toolbar 從左到右包括了 一個navigation button、一個logo、一個title和subtitle、一個或多個自定義的View和一個 action menu 這5部分。也就是這個ViewGroup 容器里面包含了這五部分內容,對應著一個界面看一下:

toolbar_5.1.png
toolbar_5.png

上面的圖就是一個Toolbar 容器從左到右的五部分內容,當然了,我們要為它設置相應的內容才行(比如:設置了nacigation button才會顯示,不設置是不會顯示出來的),否則它就只是一個空的ViewGroup,好了,到此我們就了解了一個Toolbar 是什么樣子的。那么下面我們看一下該怎么使用Toolbar。

二、Toolbar 的使用

首先看一下Toolbar 有哪些比較常用和重要的方法
XML中的常用屬性(注意開頭是自定義命名空間 xmlns:toolbar="http://schemas.android.com/apk/res-auto", 而不是 android,如果使用android:navigationIcon這種事無效的,必須使用 toolbar:navigationIcon):

  • toolbar:navigationIcon 設置navigation button

  • toolbar:logo 設置logo 圖標

  • toolbar:title 設置標題

  • toolbar:titleTextColor 設置標題文字顏色

  • toolbar:subtitle 設置副標題

  • toolbar:subtitleTextColor 設置副標題文字顏色

  • toolbar:popupTheme Reference to a theme that should be used to inflate popups shown by widgets in the toolbar.

  • toolbar:titleTextAppearance 設置title text 相關屬性,如:字體,顏色,大小等等

  • toolbar:subtitleTextAppearance 設置subtitle text 相關屬性,如:字體,顏色,大小等等

  • toolbar:logoDescription logo 描述

  • android:background Toolbar 背景

  • android:theme 主題

以上就是Toolbar比較常用的 XML 中的屬性,這些屬性也可以在代碼中設置,代碼如下:

        //設置NavigationIcon
        toolbar.setNavigationIcon(R.drawable.ic_book_list);
        // 設置navigation button 點擊事件
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        // 設置 toolbar 背景色
        toolbar.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
        // 設置 Title
        toolbar.setTitle(R.string.toolbar_title);
        //  設置Toolbar title文字顏色
        toolbar.setTitleTextColor(getResources().getColor(R.color.white));
        // 設置Toolbar subTitle
        toolbar.setSubtitle(R.string.sub_title);

        toolbar.setSubtitleTextColor(getResources().getColor(R.color.white));
        // 設置logo
        toolbar.setLogo(R.mipmap.ic_launcher);
        // 設置 NavigationIcon 點擊事件
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        //設置 Toolbar menu
        toolbar.inflateMenu(R.menu.setting_menu);
        // 設置溢出菜單的圖標
        toolbar.setOverflowIcon(getResources().getDrawable(R.drawable.abc_ic_menu_moreoverflow_mtrl_alpha));
        // 設置menu item 點擊事件
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()){
                    case R.id.item_setting:
                        //點擊設置
                        break;
                }
                return false;
            }
        });

** 以下步驟說明如何為一個Activity 添加 Toolbar**
1, 在gradle 中添加 v7 appcompat 支持庫

compile 'com.android.support:appcompat-v7:24.2.1'

2,確保你的Activity 是繼承的AppCompatActivity

public class ToolbarActivity extends AppCompatActivity{
 //...
}

3,在應用清單中,將 <application> 元素設置為使用 appcompat 的其中一個 NoActionBar主題。使用這些主題中的一個可以防止應用使用原生 ActionBar類提供應用欄。例如:

<application    android:theme="@style/Theme.AppCompat.Light.NoActionBar"    />

當然了,也可以不在application 節點,也可以在<activity> 節點設置主題,如果每個activity 都是一樣的主題,可以設置在application。主題選擇任意一個 appCompat NoActionBar 主題或則他們的子主題(比如自定義的主題,parent為appCompat 的 NoActionBar)

4,在 Activity 的布局文件中添加toolbar

 <android.support.v7.widget.Toolbar
      android:id="@+id/tool_bar_2"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@color/colorPrimary"
      toolbar:navigationIcon="@drawable/ic_book_list"
      toolbar:title="@string/toolbar_title"
      toolbar:titleTextColor="@color/white"
      toolbar:theme="@style/ToolbarTheme"
      toolbar:popupTheme="@style/ThemeOverlay.AppCompat.Light"
      >
  </android.support.v7.widget.Toolbar>

5,在Activity 中對 Toolbar 做一些相關的操作,如:設置標題,設置navigation button 點擊事件,添加溢出菜單

 private void initToolbar(){
       Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar_2);
       toolbar.setNavigationOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               finish();
           }
       });
       //添加溢出菜單
       toolbar.inflateMenu(R.menu.setting_menu);
       // 添加菜單點擊事件
       toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
           @Override
           public boolean onMenuItemClick(MenuItem item) {
               switch (item.getItemId()){
                   case R.id.item_setting:
                       //點擊設置菜單
                       break;
               }
               return false;
           }
       }); 

    }

6,溢出菜單文件如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/item_collect"
           android:icon="@drawable/ic_favorite_more"
           android:title="收藏"
           app:showAsAction="ifRoom"
        />

   <item android:id="@+id/item_setting"
         android:title="設置選項"
         app:showAsAction="never"
         />
    <item android:id="@+id/item_model"
          android:title="夜間模式"
          app:showAsAction="never"
        />
</menu>

注意 app:showAsAction ,這個屬性是設置菜單該怎么顯示,取值有5種,主要應用的有ifRoom、never、always 這三種, ifRoom 表示 如果Toolbar 上有顯示空間就顯示在Toolbar 上,如果沒有空間就展示在溢出菜單里,never 表是總是顯示在溢出菜單里,always 表示總是顯示在Toolbar 上。效果如下:

toolbar_menu1.png

點擊溢出菜單如下:


toolbar_menu2.png

** 以上就是 Toolbar 的基本使用**

三、項目中對Toolbar 的一些特殊需求

上面講了Toolbar 的基本使用方法,但是在實際的項目中可能這些還不夠,比如設計師覺得默認菜單文字顏色不好,要換菜單文字的顏色。或者溢出菜單文字的大小不好,要換文字的大小。或者需要在Toolbar 上添加自定義View等等。下面就講一下項目中遇到的幾個特殊需求。PS:我個人覺得Google 默認的文字字的顏色大小等等都是比較合適的,一般情況下不要去更改。但是有時候身不由己,產品、設計說了算。我們也就只有改了(無奈臉...)。

1,更改溢出菜單文字的顏色和文字的大小
默認情況下,彈出的溢出菜單的文字的顏色是黑色的,如下:

toolbar_menu2.png

要更改溢出菜單文字的顏色,我們只需要為Toolbar 添加一個主題,在styles.xml 文件中添加一個主題:

 <style name="ToolbarTheme" parent="Theme.AppCompat.Light">
        <!-- 設置 toolbar 溢出菜單的文字的顏色 -->
      <item name="android:textColor">@android:color/holo_red_dark</item> 
    </style>

效果如下:

overmenu1.png

看到其他的一些技術文章說的改變溢出菜單的文字顏色添加actionMenuTextColor 屬性,其實不是的,這個屬性是控制顯示在Toolbar 上的菜單的文字顏色,后面會說到。
改變溢出菜單文字的大小,在style 中添加如下代碼:

  <!-- 設置toolbar 溢出菜單的字體大小-->
  <item name="android:textSize">25sp</item>

效果如下:

overmenu2.png

2,** 更改顯示在Toolbar 上的菜單文字顏色**
更改顯示在Toolbar 上菜單文字的顏色才是用上提到的那個屬性actionMenuTextColor,注意,不要搞混淆了。顯示在Toobar上的菜單默認文字是黑色的,如下圖:

toolbar_menu12.png

如上圖所示:顯示在Toolbar 上的 發布 菜單,默認顯示是黑色,設計師肯定不干了,要你更改顏色。在 style 中添加如下代碼:

 <!-- 設置 顯示在toobar上菜單文字的顏色 -->
 <item name="actionMenuTextColor">@android:color/white</item>

特別注意,前面是沒有android: 前綴的 ,有android: 前綴是沒有效果的。最后,更改顏色后如下圖:

toolbar_menu13.png

** 順便提一下,改變顯示在Toolbar 上的菜單的文字大小和改變溢出菜單文字大小的方法一樣,都是android:textSize 這個屬性。**

最后,貼出Toolbar 主題的全部代碼:

 <style name="ToolbarTheme" parent="Theme.AppCompat.Light">
        <!-- 更換Toolbar OVerFlow menu icon -->
      <item name="actionOverflowButtonStyle">@style/OverFlowIcon</item>
        <!-- 設置 toolbar 溢出菜單的文字的顏色 -->
      <item name="android:textColor">@android:color/holo_red_dark</item>
        <!-- 設置 顯示在toobar上菜單文字的顏色 -->
      <item name="actionMenuTextColor">@android:color/white</item>
        <!-- 設置toolbar 彈出菜單的字體大小和溢出菜單文字大小-->
      <item name="android:textSize">15sp</item>
    </style>

    <style name="OverFlowIcon" parent="Widget.AppCompat.ActionButton.Overflow">
        <item name="android:src">@drawable/abc_ic_menu_moreoverflow_mtrl_alpha</item>
    </style>

最后,別忘了在Toolbar 的xml 文件中應用主題:

 <android.support.v7.widget.Toolbar
      android:id="@+id/tool_bar"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@color/colorPrimary"
      toolbar:navigationIcon="@mipmap/navigation_back_white"
      toolbar:title="@string/toolbar_title"
      toolbar:titleTextColor="@color/white"
      android:theme="@style/ToolbarTheme"
      >

  </android.support.v7.widget.Toolbar>

3,** 在Toolbar 上添加 自定義View **
這種需求很常見,如:很多 APP 里都有搜索功能,在Toolbar 上添加一個搜索框,如網易云音樂的搜索界面:

toolbar_search.png

像上面的搜索 Toolbar 也很簡單,前文已經提到過,在Toolbar 中添加View就可以了,代碼如下:

<android.support.v7.widget.Toolbar
      android:id="@+id/tool_bar_4"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@color/colorPrimary"
      android:visibility="gone"
      toolbar:navigationIcon="@mipmap/navigation_back_white"
      toolbar:theme="@style/ToolbarTheme"
      >
      <!-- ToolBar 中添加一個 編輯框 -->
      <EditText
          android:id="@+id/edit_search"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>
  </android.support.v7.widget.Toolbar>

然后,在代碼中得到這個編輯框的內容:

  private void initToolbar(){
        mToolbar3 = (Toolbar) findViewById(R.id.tool_bar_4);
        mToolbar3.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        mToolbar3.inflateMenu(R.menu.menu_search);
        
        mToolbar3.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                if(item.getItemId() == R.id.item_search){
                    // do search 
                }
                return false;
            }
        });
        // 獲取ToolBar 上的編輯框
        EditText searchEdit = (EditText) mToolbar3.findViewById(R.id.edit_search);
        // 獲取內容
        String content = searchEdit.getText().toString();
    }

效果如下:

toolbar_search2.png

很容易就可以做出一個搜索界面,以上只是舉例,Toolbar 中添加自定義View的場景還是很多的,只要知道是在Toolbar 里面添加View ,不管什么樣的需求都沒什么困難的。

** Demo 源碼請看GithubMaterialDesignSamples**

** 好了,以上就是 Toolbar 在項目中的使用和總結,水平有限,難免會有錯誤,如有什么問題,歡迎留言大家一起探討。**

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

推薦閱讀更多精彩內容