什么是 Toolbar
A Toolbar is a generalization of action bars for use within application layouts. While an action bar is traditionally part of an Activity's opaque window decor controlled by the framework, a Toolbar may be placed at any arbitrary level of nesting within a view hierarchy. An application may choose to designate a Toolbar as the action bar for an Activity using the setSupportActionBar() method.
以上是官方的介紹,簡單來說 Toolbar 是在 Android 5.0 開始推出的一個 Material Design 風(fēng)格的導(dǎo)航控件,Toolbar 可作為應(yīng)用的導(dǎo)航控件,可以替代以前的 ActionBar。比 ActionBar 更佳靈活,不一定要固定在 Activity 的頂部,而是可以嵌套在任意位置。應(yīng)用可以使用setSupportActionBar()方法將 Toolbar 設(shè)置為 Activity 的 ActionBar。
Toolbar 為我們提供了一些可定制的修改屬性,根據(jù)API文檔的介紹,主要有以下幾類:
- 可設(shè)置導(dǎo)航欄圖標(biāo)
- 可設(shè)置 App 的 logo
- 可設(shè)置標(biāo)題和子標(biāo)題
- 可添加一個或多個的自定義控件
- 可添加 ActionMenu
簡單使用
按照慣例,我們先看一下效果圖:

從效果圖來看,從左到右分別是我們設(shè)置的 導(dǎo)航欄圖標(biāo)、App的logo、標(biāo)題和副標(biāo)題、自定義控件、ActionMenu。下面我們來看具體的代碼實(shí)現(xiàn)。
- 引入v7包
由于 Toolbar 是v7包的一個控件,首先需要引入該包
implementation 'com.android.support:appcompat-v7:26.1.0'
- XML 添加 Toolbar
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary">
<!--此處可以添加自定義控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="custom"
android:textColor="@android:color/white"
android:textSize="16sp"/>
</android.support.v7.widget.Toolbar>
- 創(chuàng)建 menu_toolbar.xml 存放在 res/layout/menu 目錄下,用于為 Toolbar 設(shè)置 ActionMenu
<?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">
<!--右側(cè)搜索操作條目-->
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search_white_24dp"
android:title="搜索"
app:showAsAction="ifRoom"/>
<!--右側(cè)設(shè)置條目,收起-->
<item
android:id="@+id/action_setting"
android:title="設(shè)置"
app:showAsAction="never"/>
<item
android:id="@+id/action_help"
android:title="幫助"
app:showAsAction="never"/>
</menu>
重點(diǎn)關(guān)注一下 app:showAsAction 屬性,該屬性有以下幾種取值
- always:使菜單項(xiàng)一直顯示在 Toolbar 上
- ifRoom:如果有足夠的空間,這個值會使菜單項(xiàng)顯示在 Toolbar 上
- never:使菜單項(xiàng)永遠(yuǎn)都不出現(xiàn)在 Toolbar 上,在…的子項(xiàng)中顯示
- withText:使菜單項(xiàng)和它的圖標(biāo),菜單文本一起顯示
- Activity 中獲取并設(shè)置相關(guān)屬性值,以及事件監(jiān)聽
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 隱藏系統(tǒng)默認(rèn)的導(dǎo)航欄
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_toolbar);
ButterKnife.bind(this);
initToolbar();
}
private void initToolbar() {
// 設(shè)置ActionMenu布局(方式一)
mToolbar.inflateMenu(R.menu.menu_toobar);
// 設(shè)置logo
mToolbar.setLogo(R.mipmap.ic_launcher_round);
// 設(shè)置標(biāo)題
mToolbar.setTitle("title");
// 設(shè)置副標(biāo)題
mToolbar.setSubtitle("sub title");
// 設(shè)置標(biāo)題的字體顏色
mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
// 設(shè)置子標(biāo)題的字體顏色
mToolbar.setSubtitleTextColor(getResources().getColor(android.R.color.white));
// setSupportActionBar(mToolbar);
// 設(shè)置導(dǎo)航按鈕圖標(biāo)
mToolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp);
// 設(shè)置更多按鈕圖標(biāo)
mToolbar.setOverflowIcon(getResources().getDrawable(R.drawable.ic_more_horiz_white_24dp));
// 設(shè)置導(dǎo)航圖標(biāo)的點(diǎn)擊事件(方式一)
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mDrawerLayout.openDrawer(GravityCompat.START);
}
});
// 設(shè)置各菜單的點(diǎn)擊事件(方式一)
mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
String tip = "";
switch (id) {
case R.id.action_search:
tip = "搜索";
break;
case R.id.action_setting:
tip = "設(shè)置";
break;
case R.id.action_help:
tip = "幫助";
break;
}
Toast.makeText(ToolbarActivity.this, tip, Toast.LENGTH_SHORT).show();
return false;
}
});
}
設(shè)置 ActionMenu 和設(shè)置 點(diǎn)擊事件以上是第一種方式,還可以使用以下方式,效果一樣
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 設(shè)置ActionMenu布局(方式二)
getMenuInflater().inflate(R.menu.menu_toobar, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
String tip = "";
switch (id) {
// 對應(yīng) NavigationIcon 的點(diǎn)擊
case android.R.id.home:
tip = "菜單";
break;
case R.id.action_search:
tip = "搜索";
break;
case R.id.action_setting:
tip = "設(shè)置";
break;
case R.id.action_help:
tip = "幫助";
break;
}
Toast.makeText(ToolbarActivity.this, tip, Toast.LENGTH_SHORT).show();
return false;
}
重寫 Activity 的 onCreateOptionsMenu 和 onOptionsItemSelected 方法即可
到此已經(jīng)實(shí)現(xiàn)了一開始所看到的效果
使用中的一些坑
ActionMenu 無法顯示
如果我們在代碼中調(diào)用了setSupportActionBar方法設(shè)置了 Toolbar,此時如果使用第一種方式(mToolbar.inflateMenu(R.menu.menu_toobar))創(chuàng)建 ActionMenu 則會導(dǎo)致無法顯示,需使用第二種方式(重新 onCreateOptionsMenu)來創(chuàng)建 ActionMenu 才可以mToolbar.setTitle 不生效
如果先調(diào)用了setSupportActionBar方法后,再調(diào)用mToolbar.setTitle("title")來設(shè)置 title 的話會導(dǎo)致無法生效,需先調(diào)用mToolbar.setTitle("title")再調(diào)用setSupportActionBar才能生效NavigationIcon 與右側(cè)內(nèi)容間距太大
這個問題應(yīng)該挺多人遇到過,其實(shí)可以通過在 xml 給 Toolbar 設(shè)置app:contentInsetStartWithNavigation="0dp"或在代碼中使用setContentInsetStartWithNavigation(int)方法進(jìn)行設(shè)置,來控制NavigationIcon 與右側(cè)內(nèi)容的間距
結(jié)語
本文只是簡單地介紹了 Toolbar 和其使用,雖然該控件已經(jīng)很完善了,不過實(shí)際開發(fā)中還是為自定義導(dǎo)航欄為主,主要方便擴(kuò)展,想了解 Toolbar 的更多介紹以及相關(guān) API 請參考官方文檔(需要梯子),本文 demo 已上傳到 github