過年前發了一篇介紹 Translucent System Bar 特性的文章 Translucent System Bar 的最佳實踐,收到不少開發者的關注和反饋。今天開始寫第二篇,全面的介紹一下 Toolbar 的使用。提及 Toolbar ,可能有不少開發的童鞋還比較陌生,不要緊,請接着往下看。android
Toolbar 是在 Android 5.0 開始推出的一個 Material Design 風格的導航控件 ,Google 很是推薦你們使用 Toolbar 來做爲Android客戶端的導航欄,以此來取代以前的 Actionbar 。與 Actionbar 相比,Toolbar 明顯要靈活的多。它不像 Actionbar 同樣,必定要固定在Activity的頂部,而是能夠放到界面的任意位置。除此以外,在設計 Toolbar 的時候,Google也留給了開發者不少可定製修改的餘地,這些可定製修改的屬性在API文檔中都有詳細介紹,如:git
總之,與 Actionbar 相比,Toolbar 讓我感覺到Google滿滿的誠意。怎樣?是否已經對 Toolbar 有大概的瞭解,躍躍欲試的感受出來了有木有?接下來,咱們就一步一步的來看如何使用 Toolbar(實際上是我使用 Toolbar 踩坑填坑的血淚史,大家接下去看,我先擦個眼淚.... )。github
前面提到 Toolbar 是在 Android 5.0 纔開始加上的,Google 爲了將這一設計向下兼容,天然也少不了要推出兼容版的 Toolbar 。爲此,咱們須要在工程中引入 appcompat-v7 的兼容包,使用 android.support.v7.widget.Toolbar 進行開發。下面看一下代碼結構,一樣把重點部分已經紅圈圈出:bash
ToolbarActivity 包含了 Toolbar 的一些基本使用, ZhiHuActivity 是在熟悉了 Toolbar 後對知乎主頁面的一個高仿實現。app
layout和menu文件夾分別是上面提到的兩個Activity的佈局文件 和 actionmenu 菜單文件。ide
values、values-v1九、values-v21 中包含了一些自定義的 theme,後面用到的時候會順帶講解。佈局
咱們先來看一下 ToolbarActivity 的運行效果字體
按照效果圖,從左到右分別是咱們前面說起到的 導航欄圖標、App的logo、標題和子標題、自定義控件、以及 ActionMenu 。接着,咱們來看下佈局文件和代碼實現。優化
首先,在佈局文件 activity_tool_bar.xml 中添加進咱們須要的 Toolbar 控件ui
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da">
<!--自定義控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
</LinearLayout>
複製代碼
接着在 base_toolbar_menu.xml 中添加 action menu 菜單項
<?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="@mipmap/ic_search"
android:title="@string/menu_search"
app:showAsAction="ifRoom" />
<item
android:id="@id/action_notification"
android:icon="@mipmap/ic_notifications"
android:title="@string/menu_notifications"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_item1"
android:title="@string/item_01"
app:showAsAction="never" />
<item
android:id="@+id/action_item2"
android:title="@string/item_02"
app:showAsAction="never" />
</menu>
複製代碼
最後到 ToolbarActivity 中調用代碼拿到這 Toolbar 控件,並在代碼中作各類setXXX操做。
/**
* Toolbar的基本使用
*/
public class ToolBarActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tool_bar);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);//設置導航欄圖標
toolbar.setLogo(R.mipmap.ic_launcher);//設置app logo
toolbar.setTitle("Title");//設置主標題
toolbar.setSubtitle("Subtitle");//設置子標題
toolbar.inflateMenu(R.menu.base_toolbar_menu);//設置右上角的填充菜單
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int menuItemId = item.getItemId();
if (menuItemId == R.id.action_search) {
Toast.makeText(ToolBarActivity.this , R.string.menu_search , Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_notification) {
Toast.makeText(ToolBarActivity.this , R.string.menu_notifications , Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_item1) {
Toast.makeText(ToolBarActivity.this , R.string.item_01 , Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_item2) {
Toast.makeText(ToolBarActivity.this , R.string.item_02 , Toast.LENGTH_SHORT).show();
}
return true;
}
});
}
}
複製代碼
代碼到此已經完成了 Toolbar 的基本使用,注意,是基本使用而已!!!!!下面有幾個代碼裏面須要注意的地方:
咱們在使用 Toolbar 時候須要先隱藏掉系統原先的導航欄,網上不少人都說給Activity設置一個NoActionBar的Theme。但我的以爲有點小題大作了,因此這裏我直接在BaseActivity中調用 supportRequestWindowFeature(Window.FEATURE_NO_TITLE) 去掉了默認的導航欄(注意,個人BaseActivity是繼承了AppCompatActivity的,若是是繼承Activity就應該調用requestWindowFeature(Window.FEATURE_NO_TITLE));
若是你想修改標題和子標題的字體大小、顏色等,能夠調用setTitleTextColor、setTitleTextAppearance、setSubtitleTextColor、setSubtitleTextAppearance 這些API;
自定義的View位於 title、subtitle 和 actionmenu 之間,這意味着,若是 title 和 subtitle 都在,且 actionmenu選項 太多的時候,留給自定義View的空間就越小;
導航圖標 和 app logo 的區別在哪?若是你只設置 導航圖標( or app logo) 和 title、subtitle,會發現 app logo 和 title、subtitle 的間距比較小,看起來不如 導航圖標 與 它們兩搭配美觀;
Toolbar 和其餘控件同樣,不少屬性設置方法既支持代碼設置,也支持在xml中設置(這裏也是最最最最最坑爹的地方,如何坑爹法,請接着往下看);
剛開始使用Toolbar的時候,個人佈局文件中是這樣寫的
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da"
android:logo="@mipmap/ic_launcher"
android:navigationIcon="@mipmap/ic_drawer_home"
android:subtitle="456"
android:title="123">
<!--自定義控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
</LinearLayout>
複製代碼
在真機跑起來以後,看到的結果是下面這樣的。
此時心中真是萬千匹草泥馬在奔騰,除了設置背景色和TextView有效外,說好的 logo、navigationIcon、subtitle、title 都跑哪去了?在編譯器沒報錯又不見效果的狀況下,參考了其餘開發者的用法後找到了如下的解決方案,就是在根佈局中加入自定義屬性的命名空間
xmlns:toolbar="http://schemas.android.com/apk/res-auto"(這裏的toolbar能夠換成你想要其餘命名,作過自定義控件的童鞋相比很熟悉此用法了)
複製代碼
而後把全部用 android:xxx 設置無效的,都用 toolbar:xxx 設置便可生效。最終的佈局代碼以下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:toolbar="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da"
toolbar:navigationIcon="@mipmap/ic_drawer_home"
toolbar:logo="@mipmap/ic_launcher"
toolbar:subtitle="456"
toolbar:title="123">
<!--自定義控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
</LinearLayout>
複製代碼
到此便可解決 xml 中屬性設置失效的問題,爲何會出現這種問題呢?我猜想是由於這個控件是兼容版的控件,用 android:xxx 設置無效是的這些屬性是在兼容包中,不在默認的Android SDK中,因此咱們須要額外的引入。至於爲何IDE不報錯,估計就是bug了吧!
系統默設置了ActionMenu每一個Item的文字顏色和大小,像ToolbarActivity在Google原生5.1系統下默認效果就是下面這樣的
此時,若是我有需求要改變一下item文字顏色,應該怎麼破?我按照網上比較廣泛的解決方案,作了以下兩步的修改操做:
<style name="Theme.ToolBar.Base" parent="Theme.AppCompat.Light.NoActionBar">
<item name="actionMenuTextColor">@color/color_red</item>
</style>
複製代碼
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da"
toolbar:popupTheme="@style/Theme.ToolBar.Base">
<!--自定義控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
複製代碼
運行以後,文字的顏色的並無發生任何改變。說好的改變顏色呢.....找來找去,最後在 StackOverflow 找到一個還不錯的解決方案,就是把上面的的 actionMenuTextColor 屬性換成 android:textColorPrimary 便可解決,最終獲得下面的運行效果。
這種方法也有一個小缺點,若是我把自定義控件換成Button,你會發現Button默認的文字顏色也變成了紅色。因此,此處若是有朋友有更好的解決方案,請留言賜教。
若是你想要修改 ActionMenu Item 的文字大小,也能夠在theme中設置加上以下設置
<item name="android:textSize">20sp</item>
複製代碼
以上就是目前使用 Toolbar 一些比較折騰的坑,感受 Google 對 Toolbar 這些坑,還能夠進一步優化優化,否則就坑苦了開發者們了。
爲了加深一下 Toolbar 的開發體驗,咱們使用 Toolbar 來實現知乎主頁的效果!先來看下知乎主頁的效果
若是前面的內容你看明白,想擼出這個界面無非是幾分鐘的事情,下面就直接上代碼,不作贅述了。
ZhiHuActivity界面代碼
public class ZhiHuActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zhi_hu);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.inflateMenu(R.menu.zhihu_toolbar_menu);
toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);
toolbar.setTitle(R.string.home_page);
toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
}
}
複製代碼
zhihu_toolbar_menu.xml 菜單
<?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="@mipmap/ic_search"
android:title="@string/menu_search"
app:showAsAction="ifRoom" />
<item
android:id="@id/action_notification"
android:icon="@mipmap/ic_notifications"
android:title="@string/menu_notifications"
app:showAsAction="ifRoom" />
<item
android:id="@id/action_settings"
android:orderInCategory="100"
android:title="@string/menu_settings"
app:showAsAction="never" />
<item
android:id="@id/action_about"
android:orderInCategory="101"
android:title="@string/menu_about_us"
app:showAsAction="never" />
</menu>
複製代碼
activity_zhi_hu.xml 佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da"
android:theme="@style/Theme.ToolBar.ZhiHu">
</android.support.v7.widget.Toolbar>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:background="@mipmap/ic_zhihu_logo" />
</RelativeLayout>
</LinearLayout>
複製代碼
styles.xml 中的 Theme.ToolBar.ZhiHu,給 Toolbar 設置android:theme用的
<resources>
...
...
<style name="Theme.ToolBar.ZhiHu" parent="Theme.AppCompat.Light.NoActionBar">
<item name="actionOverflowButtonStyle">@style/ActionButton.Overflow.ZhiHu</item>
</style>
<style name="ActionButton.Overflow.ZhiHu" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
<item name="android:src">@mipmap/ic_menu_more_overflow</item>
</style>
</resources>
複製代碼
最終獲得下面這樣的效果
這裏在 Toolbar 設置 android:theme="@style/Theme.ToolBar.ZhiHu" 主要是爲了替換系統右上角三個點的圖標,若是不設置,則會成系統默認主題的樣子。
最後,再給知乎的主頁面作個小小的優化,它在 Android 4.4 上運行仍是可以看到一條黑乎乎的通知欄,爲此我把 Toolbar 和 Translucent System Bar 的特性結合起來,最終改進成下面的效果(附上 Android4.4 和 5.1 上的運行效果)。
若是你還不知道 Translucent System Bar 的特性怎麼使用,請查看個人上一篇文章:Translucent System Bar 的最佳實踐
關於 Toolbar 的使用就介紹到此,原本是懷着很簡單就能夠上手的心態來使用,結果發現仍是有不少坑須要填。果真仍是驗證了一句老話
紙上得來終覺淺,絕知此事要躬行
複製代碼
一樣,分享即美德,須要源代碼的童鞋,請戳:github.com/D-clock/And…
做者:D_clock愛吃蔥花
連接:www.jianshu.com/p/79604c3dd…