ToolBar隨心定制

臨近年末,項(xiàng)目沒什么新需求了,主要做一些code review和代碼重構(gòu)的工作。有一個(gè)工作是將我們app中的TitleBar替換為Android的原生控件ToolBar,ToolBar出來這么久,相信大家都不會(huì)陌生了。替換的工作并不難,但因?yàn)槲覀傾pp原來的TitleBar是一個(gè)相對(duì)布局中間放了一些ImageButton和TextView等控件組成的,并不符合ToolBar的原生風(fēng)格,所以我一開始打算放棄替換,但經(jīng)過一番Google,發(fā)現(xiàn)原來還是可以輕松實(shí)現(xiàn)的,不得不感嘆ToolBar的定制性真得很強(qiáng)。

我需要替換的TitleBar樣式
原生風(fēng)格的ToolBar

關(guān)于ToolBar的基本用法網(wǎng)上一大堆,不會(huì)的童鞋可以自己去Google,我這里簡(jiǎn)單總結(jié)一下如何更自由的定制ToolBar。

一. Title居中

ToolBar默認(rèn)的主Title是居左的,但是我們可以通過自定義ToolBar的子View來達(dá)到顯示居中Title的效果。

<android.support.v7.widget.Toolbar
    android:id="@+id/toolBar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

    <TextView
        android:id="@+id/toolbar_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="自定義標(biāo)題"
        android:textColor="@color/black"
        android:textSize="@dimen/title_center_textsize" />

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

這樣還可以單獨(dú)控制中間標(biāo)題的字體顏色和大小等。使用TextView作為title后,toolbar.setTitle(...)就可以設(shè)置為空或者不用設(shè)置了。

二. 在ToolBar左側(cè)放置Menu

在ToolBar添加Menu時(shí),默認(rèn)都是出現(xiàn)在右側(cè)的,但我的需求是在左側(cè)放置兩個(gè)Menu,本來想通過設(shè)置NavigationIcon和logo來解決,但如果這樣,只能設(shè)置兩個(gè)圖標(biāo)在左邊,而且圖標(biāo)之間的間距沒辦法調(diào)整,所以靈活性很差。后來發(fā)現(xiàn)一個(gè)非常好用的控件ActionMenuView,以前它可以搭配ActionBar來使用,現(xiàn)在同樣可以用來自定義ToolBar的菜單。

    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/title_height"
        android:background="@color/title_background"
        android:minHeight="@dimen/title_height"
        app:contentInsetLeft="0dp"
        app:contentInsetStart="0dp"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        <android.support.v7.widget.ActionMenuView
            android:id="@+id/action_menu_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent" />

        <TextView
            android:id="@+id/toolbar_title"
            style="@style/TitleBar.Text.Center"
            android:layout_width="wrap_content"
            android:layout_height="match_parent" />


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

將ActionMenuView放在ToolBar子布局中的第一個(gè),它就會(huì)繪制在左側(cè),還需要注意給ToolBar設(shè)置下面的屬性(而且需要注意,這里要使用"app:xxx"而不是"Android:xxx",否則會(huì)有兼容性問題),因?yàn)楫?dāng)沒有設(shè)置NavigationIcon和logo時(shí),ToolBar左側(cè)默認(rèn)有一小段空白:

app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"

然后我們需要給ActionMenuView加載菜單,代碼很簡(jiǎn)單:

ActionMenuView actionMenuView = (ActionMenuView) toolbar.findViewById(R.id.action_menu_view);
getMenuInflater().inflate(R.menu.menu_toolbar_left, actionMenuView.getMenu());
// 點(diǎn)擊事件
actionMenuView.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() {
    @Override
    public boolean onMenuItemClick(MenuItem item) {
        return false;
    }
});

R.menu.menu_toolbar_left.xml文件就是放置在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/left_back_btn"
        android:icon="@drawable/ic_titlebar_back"
        android:title="后退"
        app:showAsAction="always"/>

    <item
        android:id="@+id/left_text_btn"
        android:title=""
        app:actionLayout="@layout/menu_layout_text_btn"
        app:showAsAction="always"/>

    <item
        android:id="@+id/left_icon_btn"
        android:icon="@drawable/ic_launcher"
        android:title=""
        app:showAsAction="always"/>

</menu>
左邊菜單顯示效果

細(xì)心的同學(xué)應(yīng)該看到我第二個(gè)id為left_text_btn的菜單使用了app:actionLayout屬性,這是使當(dāng)前菜單顯示你指定的layout布局,也是非常方便的定制功能。因?yàn)門oolBar中所有菜單的顏色必須統(tǒng)一指定(通過在AppTheme中指定"android:actionMenuTextColor"屬性),沒辦法分開設(shè)置,所以如果需要單獨(dú)設(shè)置某個(gè)菜單的顏色,可以指定它的app:actionLayout,上面的"@layout/menu_layout_text_btn"布局為一個(gè)簡(jiǎn)單的TextView,就不貼了,也可以通過代碼指定:

MenuItem menuItem = actionMenuView.getMenu().findItem(R.id.left_text_btn);
menuItem.setActionView(R.layout.menu_layout_text_btn);

還有一個(gè)細(xì)節(jié)可能也有人關(guān)注到,就是如果菜單按鈕是通過icon屬性設(shè)置的圖標(biāo)按鈕,長(zhǎng)按就會(huì)出現(xiàn)Toast文字(title屬性設(shè)置的文字)提示這個(gè)圖標(biāo)按鈕的作用,即便title設(shè)為空字符串,也還是會(huì)彈出Toast,這是Android系統(tǒng)的默認(rèn)設(shè)置,無法取消,如果實(shí)在不想要這個(gè)提示,可以通過指定其app:actionLayout為一個(gè)自定義的ImageButton來實(shí)現(xiàn)。注意當(dāng)使用app:actionLayout屬性定制菜單時(shí),點(diǎn)擊事件就需要通過設(shè)置app:actionLayout指定的layout中的View的Click監(jiān)聽來實(shí)現(xiàn)了

// 此時(shí)menuItem.getActionView()獲取的View就是自定義的ImageButton或TextView
menuItem.getActionView().setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        
    }
});

默認(rèn)的MenuItem點(diǎn)擊效果為一個(gè)小圓形的水波紋效果,查看自帶style是通過下面的資源文件實(shí)現(xiàn)的,自定義時(shí)可以指定為它以保持點(diǎn)擊效果一致:

android:background="?attr/actionBarItemBackground"

三. Menu的間距和文字屬性設(shè)置

有時(shí)我們需要設(shè)置按鈕文字的顏色以及大小,還需要調(diào)整相鄰按鈕之間的間距,比如上圖中可能有人會(huì)覺得"<"后退按鈕和“關(guān)閉”按鈕之間的間距太大了,這要如何調(diào)整呢?都可以通過指定Theme中的屬性來設(shè)置。

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:actionMenuTextColor">@color/primary</item>
        <item name="android:actionMenuTextAppearance">@style/ActionMenuTextAppearance</item>
        <item name="android:actionButtonStyle">@style/ActionButtonStyle</item>
    </style>

android:actionMenuTextColor屬性用來指定菜單文字的顏色,android:actionMenuTextAppearance是用來指定菜單文字的大小等屬性

    <style name="ActionMenuTextAppearance" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Menu">
        <item name="android:textSize">@dimen/title_right_textsize</item>
        <item name="android:textStyle">normal</item>
    </style>

android:actionButtonStyle可以修改按鈕的大小和間距

    <style name="ActionButtonStyle" parent="Widget.AppCompat.Light.ActionButton">
        <item name="android:minWidth">44dp</item>
        <item name="android:paddingLeft">10dp</item>
        <item name="android:paddingRight">10dp</item>
    </style>

這里因?yàn)閍pi17以下使用的是paddingLeft和paddingRight,而api17以上使用的是paddingStart和paddingEnd(通過查看Widget.AppCompat.Light.ActionButton的style源碼也可以看到),所以這里需要新建values-v17文件夾,在其下新建styles.xml來專門指定api17以上的ActionButtonStyle:

    <style name="ActionButtonStyle" parent="Widget.AppCompat.Light.ActionButton">
        <item name="android:minWidth">44dp</item>
        <item name="android:paddingStart">10dp</item>
        <item name="android:paddingEnd">10dp</item>
    </style>

ActionButton默認(rèn)的android:minWidth屬性值為48dp,默認(rèn)左右的padding值為12dp。


ActionButton默認(rèn)的android:minWidth屬性值

所以如果我們需要修改按鈕的間距,可以修改以上三個(gè)屬性值,改小之后可以明顯看到間距減小


minWidth改為20dp,左右padding改為0dp的效果

四. 總結(jié)

以上就是這次替換的一小點(diǎn)經(jīng)驗(yàn)總結(jié),右邊的菜單通過直接給ToolBar添加Menu就可以了,當(dāng)然你也可以通過自定義的方式實(shí)現(xiàn)。通過以上幾點(diǎn),我們可以看到ToolBar的非常靈活的可定制性,不僅如此,如果你的菜單還有更不一樣的地方,可以把ToolBar中的內(nèi)容全部通過自定義布局來實(shí)現(xiàn),也就是全部通過ToolBar的子View們來展示ToolBar的內(nèi)容。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容