寫在前面
bar在英語中有“門閂(shuān)”之意,我想大家一看到“閂”這個字就能馬上聯(lián)想到bar是啥了。當(dāng)然Android中對bar的定義和門閂還是有不少區(qū)別的千绪。Android中的bar有引導(dǎo)使用之作用池摧,快速讓用戶了解當(dāng)前頁面的功能和相關(guān)操作等荔泳。本著這個原則就有了下面的bar的發(fā)展史橙数。
從Titlebar到Actionbar
在3.0之前尊流,Android在UI設(shè)計上還是比較簡單粗暴的,當(dāng)時對這個bar的作用定義也極為簡單灯帮,就是為顯示當(dāng)前頁面的標(biāo)題奠旺,名字都命名成了Titlebar蜘澜,意為標(biāo)題bar。對這個bar能做的操作也很單一响疚,設(shè)置標(biāo)題,再或者加個logo啥的瞪醋,再有復(fù)雜的就得自己自定義View了忿晕。這個bar長相就如下圖所示,可以說丑到爆了银受。和當(dāng)時iOS漂亮的界面簡直一個天一個地践盼,那個時代可以說是Android的試水期,只追求功能可用宾巍,而其他方面就不管了咕幻。
當(dāng)時Android在操作設(shè)計上是有物理返回按鈕的,所以這個Titlebar連返回都不支持顶霞。而在那個設(shè)計往往都要對標(biāo)iOS的時代肄程,Android程序員只能自己去擴展這個功能單一的Titlebar了。自己辛苦得模仿實現(xiàn)iOS應(yīng)用上那些漂亮的導(dǎo)航欄功能选浑。
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_bar);
經(jīng)過幾年的發(fā)展蓝厌,到Android 2.3版本,Android的各大功能基本穩(wěn)定了古徒,Android界開始對美和使用方便性有了強烈的呼聲拓提。于是2011年Google發(fā)布了Android 3.0版本,這個版本的Android在UI設(shè)計上進(jìn)行了大改隧膘,除了引入了大家熟悉的Fragment外代态,也開始把Titlebar替換為Actionbar。Actionbar顧名思義疹吃,這個bar就不當(dāng)當(dāng)只是展示標(biāo)題了蹦疑,而是加入了Action(動作)。Android3.0的發(fā)布相當(dāng)于Android一個試錯的舊時代的結(jié)束互墓,一個高速發(fā)展的新時代的開始必尼,雖然Android3.0本身應(yīng)用的范圍很小。
Actionbar時代
Actionbar主要功能除了顯示Title外篡撵,還提供了一致的導(dǎo)航和視覺體驗判莉,突出了應(yīng)用的關(guān)鍵操作。比如你可以使用SetDisplayHomeAsUpEnabled(true)
添加向上導(dǎo)航育谬,這樣在點擊Actionbar左邊的應(yīng)用圖標(biāo)時會返回父視圖券盅。
你還可以使用Menu的方式來添加當(dāng)前頁面的操作按鈕。
你甚至還可以在Actionbar中自定義自己的View膛檀,比如你可以
或者在Actionbar中加入頁面切換的功能锰镀,配合Fragment的機制
另外Actionbar還提供了樣式設(shè)定娘侍,多屏幕適配等等功能。算是解決了Titlebar的痛點泳炉,Android在頂部導(dǎo)航這一塊終于有了自己的風(fēng)格憾筏,而不再唯iOS是瞻。
啊哈花鹅,Toolbar
又隨著時代的發(fā)展氧腰,到了2014年,Android5.0發(fā)布刨肃,這個版本的發(fā)布標(biāo)志著Android又進(jìn)入了一個新時代古拴,快速爆發(fā)的時代過去了,從現(xiàn)在起真友,要變得優(yōu)雅黄痪,要有自己統(tǒng)一的風(fēng)格。所以在這個版本上Google推出了Material Design設(shè)計語言盔然。然后Actionbar就被重整了桅打,Actionbar雖方便使用,功能也很強大轻纪。但它最大的缺點就是不夠靈活油额,比如它默認(rèn)只能在頂部,要想把Actionbar移到屏幕其它位置就會非常麻煩刻帚,因為它在設(shè)計上是綁定在DecorView的潦嘶。你可以到com.android.internal.policy.DecorView
中看到相關(guān)源碼,比如有下面這段崇众,把Actionbar固定在了頂部掂僵,并且橫向填充。
mShowPrimaryActionModePopup = new Runnable() {
public void run() {
mPrimaryActionModePopup.showAtLocation(
mPrimaryActionModeView.getApplicationWindowToken(),
Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
endOnGoingFadeAnimation();
...
}
};
為了滿足Material Design優(yōu)雅而靈活的設(shè)計原則顷歌,Google推出了更加靈活的Toolbar锰蓬。你可以在一個Activity中聲明多個Toolbar并且放在任意位置。并且你可以在自己的Toolbar中塞入任何你想要的View眯漩。Toolbar不是Actionbar的替代芹扭,Toolbar是Actionbar的布局方式的擴展,就像一個家庭的小孩長大了赦抖,它可以去外面干更多的事情舱卡,而也可以回家繼續(xù)做一個晚輩。所以我們可以自己定義一個Toolbar队萤,然后調(diào)用setActionBar()
來讓這個Toolbar充當(dāng)Actionbar的功能轮锥,前提你需要把當(dāng)前Activity主題或feature設(shè)為NoActionBar。
Toolbar的使用
這里只簡單介紹下Toolbar的一種用法要尔。關(guān)于Toolbar的詳細(xì)用法舍杜,可以參考:Google的官方文檔新娜。我們用向Toolbar中加入一個搜索按鈕來舉個例子。
首先你需要在布局中加入toolbar既绩,它可以如普通View一樣被放在布局的任意位置概龄,如下代碼布局所示。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.hadcn.test.MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
<TextView
android:layout_below="@+id/toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</RelativeLayout>
并且在Activity的onCreate方法中把該toolbar設(shè)置為ActionBar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setLogo(R.mipmap.ic_launcher);
注:該Activity的Theme需要是NoActionBar的
這樣就成功用toolbar替換了本來的ActionBar了熬词,接下來我們要向這個toolbar加入搜索按鈕旁钧,因為該toolbar已經(jīng)作為actionbar了,所以添加方式也如操作ActionBar一樣互拾,首先創(chuàng)建一個menu文件,內(nèi)容如下:
<?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/action_search"
android:icon="@android:drawable/ic_menu_search"
android:title="Search"
app:showAsAction="ifRoom"/>
</menu>
最后在對應(yīng)的Activity中加入該menu嚎幸,成功后颜矿,就能得到如下圖所示的效果啦。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.test_menu, menu);
return true;
}
TIPS:有人可能注意到在使用showAsAction時使用了app作為命名空間嫉晶,而非使用android骑疆。這個是一個歷史遺留問題,因為ActionBar是在Android 3.0上引入的替废,它也具有android:showAsAction這個屬性箍铭,所以appcompat-v7包為了向下兼容,就用了自定義屬性來避免沖突椎镣。
原文地址:http://pengtao.me/2017-06-04/titlebar-actionbar-toolbar/
作者簡介
彭濤(@彭濤me) 致力于讓技術(shù)變得易懂且有趣
個人博客:http://pengtao.me
簡書:http://www.reibang.com/u/f9246f41945e
GitHub:https://github.com/CPPAlien