Toolbar使用詳解

Toobar與ActionBar

從Android3.0(API level 11)開始,所有使用默認(rèn)主題的activity都自帶一個ActionBar,但是隨著Android版本的迭代,ActionBar的特性不斷增加,從而導(dǎo)致了在不同Android系統(tǒng)的設(shè)備上,ActionBar的顯示不一致。

從Android5.0(API level 21)開始,引進(jìn)了Toolbar,它包含了ActionBar最近添加的大多數(shù)特性,同時添加到了支持庫中,使得在低版本設(shè)備上也可以使用Toolbar。

Toolbar與ActionBar的區(qū)別:

  • ToolBar就是一個View,跟其它View一樣包含在布局中。
  • 像常規(guī)View一樣,Toolbar很容易來放置、實現(xiàn)動畫以及控制。
  • 一個Activity中可以有多個Toolbar。

Toolbar是簡單使用

  1. 在應(yīng)用的build.gradle中添加v7 appcompat支持庫。
com.android.support:appcompat-v7:24.1.1
  1. 讓Activity繼承自AppCompatActivity。
public class MyActivity extends AppCompatActivity {
    // ...
} 
  1. 在AndroidManifest.xml文件中,設(shè)置<application>元素使用appcompat中的某個NoActionBar主題,從而來去除使用ActionBar來提供操作欄。
<application
        android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
  1. 在activity的布局中添加Toolbar。
<android.support.v7.widget.Toolbar
   android:id="@+id/my_toolbar"
   android:layout_width="match_parent"
   android:layout_height="?attr/actionBarSize"
   android:background="?attr/colorPrimary"
   android:elevation="4dp"
   android:theme="@style/ThemeOverlay.AppCompat.ActionBar"  
   app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
  1. 在activity的onCreate()方法中,調(diào)用setSupportActionBar()方法,并傳入toolbar,這樣就會將toolbar設(shè)置為activity的操作欄了。
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);
    Toolbar toolbar = (Toolbar) findViewById(R.id.my_toolbar);
    setSupportActionBar(toolbar);
}

運行之后,效果圖如下:

Toolbar簡單使用.png

至此,activity有了一個基本的操作欄。可以通過獲取的toolbar的引用,調(diào)用相關(guān)API來實現(xiàn)更多操作,例如隱藏或顯示操作欄。

Toolbar元素

上面的效果圖中,只顯示了App的名稱,但是Toolbar可以包含以下元素:

  • 導(dǎo)航按鈕
  • 應(yīng)用的Logo
  • 標(biāo)題和子標(biāo)題
  • 若干個自定義View
  • 動作菜單

好的,接下來我們就讓它們?nèi)匡@示出來。

  1. 顯示導(dǎo)航按鈕、應(yīng)用的Logo、標(biāo)題和子標(biāo)題。
// 顯示應(yīng)用的Logo
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayUseLogoEnabled(true);
getSupportActionBar().setLogo(R.mipmap.ic_launcher);

// 顯示標(biāo)題和子標(biāo)題  
getSupportActionBar().setDisplayShowTitleEnabled(true);
toolbar.setTitle("ToolbarDemo");
toolbar.setSubtitle("the detail of toolbar");
// 顯示導(dǎo)航按鈕
toolbar.setNavigationIcon(R.drawable.icon_back);
  1. 顯示動作菜單。
    首先在res/menu目錄下的xml文件中定義的,要添加幾個動作,則在<menu>節(jié)點下添加幾個item。
<?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/toolbar_action1"
        android:icon="@drawable/icon_weibo_timeline_mine"
        android:title="Action"
        app:showAsAction="always"/>

    <item
        android:id="@+id/toolbar_action1"
        android:icon="@drawable/icon_weibo_timeline_mine"
        android:title="Action"
        app:showAsAction="never"/>

  </menu>

item的icon和title屬性顧名思義,而app:showAsAction屬性則是用來指定這個動作是放置在操作欄上,還是溢出菜單中。當(dāng)它的值設(shè)置為”ifRomom”時,如果操作欄有空間放置,則放置在操作欄上,否則放置到溢出菜單中。當(dāng)它的值設(shè)置為”always”,這個動作將總是放置在操作欄上。當(dāng)它的值設(shè)置為”never”,這個動作將總是放置在溢出菜單中。

之后重寫activity的onCreateOptionsMenu()方法,設(shè)置顯示的menu資源:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_toolbar_demo, menu);
    return true;
}

當(dāng)點擊了按鈕,可以通過重寫activity的onOptionsItemSelected()方法來進(jìn)行處理:

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
      switch (item.getItemId()) {
          case R.id.toolbar_action1:
              // do something
              return true;
          default:
              // If we got here, the user's action was not recognized.
              // Invoke the superclass to handle it.
              return super.onOptionsItemSelected(item);

      }
  }
  1. 顯示自定義View

因為Toolbar是ViewGroup的子類,因此可以向其內(nèi)部添加View進(jìn)行顯示。這里我們簡單的添加一個TextView顯示一個文本。

<android.support.v7.widget.Toolbar
  android:id="@+id/toolbar"
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="?attr/actionBarSize"
  android:background="?attr/colorPrimary"
  android:elevation="4dp"
  android:theme="@style/ToolbarTheme"
  app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
  app:titleTextAppearance="@style/Toolbar.TitleText">

  <TextView
      android:id="@+id/toolbar_title"
      style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      android:text="自定義"
      android:textSize="21sp"/>

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

好了,所有的元素都添加到了Toolbar上,運行效果圖如下:

Toolbar元素

Toolber復(fù)用

應(yīng)用中有很多界面,每個Activity一般都需要操作欄,且大多數(shù)activity的操作欄的元素是一致的,那每個布局文件里面都寫這么多資源文件是累贅的。因此可以對Toolbar進(jìn)行復(fù)用,使得布局文件看起來更精煉,更改Toolbar整體效果,如背景之類的可以更方便。

首先,在布局文件toolbar.xml中定義Toolbar。

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:contentInsetLeft="0dp"
    android:contentInsetStart="0dp"
    android:elevation="4dp"
    android:theme="@style/ToolbarTheme"
    app:navigationIcon="@drawable/icon_back"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    app:titleTextAppearance="@style/Toolbar.TitleText">

    <!--  any custom view -->

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

之后,在需要添加Toolbar的地方引入這個布局資源。

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

最后,在BaseActivity(一般app都會有)中的onCreate()方法設(shè)置Toolbar。注意,這個時候Activity不再繼承AppCompatActivity,而是繼承BaseActivity,而BaseActivity繼承AppCompatActivity。BaseActivity部分代碼如下:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    if (toolbar != null) {
        setSupportActionBar(toolbar);

        mToolbarHelper = new ToolbarHelper(toolbar);

        hanldeToolbar(mToolbarHelper);
    }
}

protected void hanldeToolbar(ToolbarHelper toolbarHelper) {}

public static class ToolbarHelper {

    private Toolbar mToolbar;

    public ToolbarHelper(Toolbar toolbar) {
        this.mToolbar = toolbar;
    }

    public Toolbar getToolbar() {
        return mToolbar;
    }

    public void setTitle(String title) {
        TextView titleTV = (TextView) mToolbar.findViewById(R.id.toolbar_title);
        titleTV.setText(title);
    }
}

代碼中首先獲取到Toolbar將其設(shè)置為操作欄,之后創(chuàng)建了一個ToolbarHelper對象,ToobarHelper主要是封裝了下Toolbar,并提供操作自定義View的方法。然后調(diào)用hanldeToolbar()方法,子Activity通過重寫這個方法,可以對Toolbar進(jìn)行定制操作。

在真實項目中應(yīng)用Toolbar

在上面我們看到了顯示所有Toolbar元素的效果圖,肯定會說,這跟我們產(chǎn)品設(shè)計的不一樣,跟應(yīng)用中所需要的不一樣。一般我們應(yīng)用中大多是這樣的:

常用Toolbar.png

觀察下,首先左邊是一個返回按鈕,中間是標(biāo)題,有可能右邊是文本或者按鈕來提供分享、編輯之類的操作。接下來,我們來看看如何實現(xiàn)。

  1. 實現(xiàn)返回按鈕,在之前我們設(shè)置過顯示導(dǎo)航按鈕、logo、標(biāo)題及子標(biāo)題。現(xiàn)在將導(dǎo)航按鈕作為返回按鈕,設(shè)置為UI提供的圖標(biāo),而logo和標(biāo)題類的設(shè)置不顯示就可以了。

接下來就是設(shè)置事件監(jiān)聽了,還記得添加按鈕時的事件處理么?一樣的都是在onOptionsItemSelected()進(jìn)行處理,它的id是android.R.id.home:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {
      case android.R.id.home:
          FragmentManager fm = getSupportFragmentManager();
          if (fm != null && fm.getBackStackEntryCount() > 0) {
              fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
          } else {
              finish();
          }
          return true;
      default:
          return super.onOptionsItemSelected(item);
  }
}
  1. 實現(xiàn)中間標(biāo)題的顯示。在上一步我們禁用了Toolbar原本顯示在左邊的標(biāo)題,中間的標(biāo)題我們可以通過向Toolbar中添加TextView實現(xiàn),與之前顯示Toolbar上所有元素中的自定義View是一樣的。對于更改標(biāo)題,則通過上面Toolbar復(fù)用所提到的ToolbarHelper進(jìn)行操作。
  2. 右邊的文本及圖標(biāo)顯示。這個可以使用Toolbar本身的menu(前面已經(jīng)介紹過),也可以將其作為自定義View。

總之,這三部分(左邊+中間+右邊)實現(xiàn)方式大致如此,根據(jù)你的項目,合理地進(jìn)行安排。

最后,附上源碼地址:
https://github.com/FILWAndroid/DevJourney

關(guān)于源碼:

  1. 不只是本文涉及的代碼,會包含很多知識點的代碼,應(yīng)該都會在我的簡書中進(jìn)行介紹。
  2. 有可能代碼與本文中所貼出來的有差異,但應(yīng)該都是我覺得更好的方式吧。
  3. 歡迎大家對我進(jìn)行批評教育。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內(nèi)容