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是簡單使用
- 在應(yīng)用的build.gradle中添加v7 appcompat支持庫。
com.android.support:appcompat-v7:24.1.1
- 讓Activity繼承自AppCompatActivity。
public class MyActivity extends AppCompatActivity {
// ...
}
- 在AndroidManifest.xml文件中,設(shè)置<application>元素使用appcompat中的某個NoActionBar主題,從而來去除使用ActionBar來提供操作欄。
<application
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
- 在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"/>
- 在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);
}
運行之后,效果圖如下:
至此,activity有了一個基本的操作欄。可以通過獲取的toolbar的引用,調(diào)用相關(guān)API來實現(xiàn)更多操作,例如隱藏或顯示操作欄。
Toolbar元素
上面的效果圖中,只顯示了App的名稱,但是Toolbar可以包含以下元素:
- 導(dǎo)航按鈕
- 應(yīng)用的Logo
- 標(biāo)題和子標(biāo)題
- 若干個自定義View
- 動作菜單
好的,接下來我們就讓它們?nèi)匡@示出來。
- 顯示導(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);
- 顯示動作菜單。
首先在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);
}
}
- 顯示自定義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上,運行效果圖如下:
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)用中大多是這樣的:
觀察下,首先左邊是一個返回按鈕,中間是標(biāo)題,有可能右邊是文本或者按鈕來提供分享、編輯之類的操作。接下來,我們來看看如何實現(xiàn)。
- 實現(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);
}
}
- 實現(xiàn)中間標(biāo)題的顯示。在上一步我們禁用了Toolbar原本顯示在左邊的標(biāo)題,中間的標(biāo)題我們可以通過向Toolbar中添加TextView實現(xiàn),與之前顯示Toolbar上所有元素中的自定義View是一樣的。對于更改標(biāo)題,則通過上面Toolbar復(fù)用所提到的ToolbarHelper進(jìn)行操作。
- 右邊的文本及圖標(biāo)顯示。這個可以使用Toolbar本身的menu(前面已經(jīng)介紹過),也可以將其作為自定義View。
總之,這三部分(左邊+中間+右邊)實現(xiàn)方式大致如此,根據(jù)你的項目,合理地進(jìn)行安排。
最后,附上源碼地址:
https://github.com/FILWAndroid/DevJourney
關(guān)于源碼:
- 不只是本文涉及的代碼,會包含很多知識點的代碼,應(yīng)該都會在我的簡書中進(jìn)行介紹。
- 有可能代碼與本文中所貼出來的有差異,但應(yīng)該都是我覺得更好的方式吧。
- 歡迎大家對我進(jìn)行批評教育。