Android ToolBar 完全解析

       在上一篇文章中我們詳細介紹了什麼是 Material Design,以及一些 MD 的風格,接下來我們就來進行實戰,而 ToolBar 將會是我們第一個來進行實戰的 Material 控件,雖然對 ToolBar 還不是那麼熟悉,但是相信另一個相關的控件我們是非常熟悉的,那就是 ActionBar,相信這個大家都是很熟悉了,沒錯,活動的頂部導航的那個標題欄其實就是 ActionBar,我們之前的應用開發中一定都有 ActionBar 的相關使用,不過 ActionBar 由於其設計原因,應用有一定的侷限性,比如被限定只能位於活動的頂部,從而不能實現一些 MD 風格,因此官方已經不建議使用 ActionBar 了,強力推薦使用 ToolBar,那麼 ToolBar 到底好在哪裏,ToolBar 的強大之處就在於,它不僅繼承了 ActionBar 的所用功能,而且靈活性很高,可以配合一些其他的控件來完成一些 MD 的效果,扯淡就到這裏,接下來開始演繹

新建一個 MaterialDesign 項目,我們馬上開始吧


一、項目的主題默認是在哪裏指定的?


       首先我們要知道任何一個新建項目,默認都會顯示 ActionBar,那麼這個 ActionBar 到底是從哪裏來的,其實這是根據項目中指定的主題來顯示的,這裏我們不妨打開我們新建項目的清單文件 AndroidManifest.xml 文件來看一下,如下所示:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.qiudengjiao.materialdesign">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

可以看到,這裏使用 android:theme 屬性指定了一個 AppTheme 的主題,那麼我們再具體去看看這 AppTheme 的主題是怎麼定義的,打開 AppTheme 定義如下:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

這裏定義了一個叫 AppTheme 的主題,然後指定它的 parent 主題是 Theme.AppCompat.Light.DarkAcionBar,這個 DarkActionBar 是一個深色的 ActionBar 主題,我們之前所有的項目中自帶的 ActionBar 就是因爲指定了這個主題纔出現的,顯示效果如下圖: 



現在我們就要使用 ToolBar 來替代 ActionBar,因此需要指定一個不帶 ActionBar 的主題,通常有如下兩種主題可選:

  • Theme.AppCompat.NoActionBar
  • Theme.AppCompat.Light.NoActionBar
其中 Theme.AppCompat.NoActionBar 表示深色主題,它會將界面的主題顏色設計成深色,陪襯顏色設計成淡色,而 Theme.AppCompat.Light.NoActionBar 表示淡色主題,他會將界面的主題顏色設置成淡色,陪襯顏色設置成深色,具體效果如下圖所示:


這裏我們看到上圖中沒有了頂部的導航欄,左邊是 Theme.AppCompat.NoActionBar 深色主題的,右邊是 Theme.AppCompat.Light.NoActionBar 淺色主題的,也是我們項目中常用的,然後我們觀察下 AppTheme 中的屬性重寫如下:

 <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

這裏重寫了 colorPrimary、colorPrimaryDark、colorAccent  這 3 個屬性的顏色,那麼這 3 個屬性的顏色分別代表着什麼位置的顏色呢?我們用語言太難描述清楚,直接上圖吧,這張圖大家也見過,來自 Google 官方網站,如下:





可以看到每個屬性值指定的顏色一目瞭然,代碼描述如下:

<style name="AppTheme.NoActionBar">
    <!--狀態欄顏色-->
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <!--控制各個控件被選中時的顏色-->
    <item name="colorAccent">@color/colorAccent</item>
    <!--頁面背景色-->
    <item name="android:windowBackground">@color/windowBackg</item>
    <!--底部導航欄顏色-->
    <item name="android:navigationBarColor">@color/navigationColor</item>
    <!--Appbar背景色-->
    <item name="android:colorPrimary">@color/colorPrimary</item>
    <!--ToolBar上的Title顏色-->
    <item name="android:textColorPrimary">@color/textColorPrimary</item>
    <!--各個控制控件的默認顏色-->
    <item name="android:colorControlNormal">@color/colorControlNormal</item>
</style>

上面我們已經將 ActionBar 隱藏起來了,接下來我們來看一下如何使用今天要學習的主角 ToolBar,看 ToolBar 如何來替代 ActionBar

二 、創建 ToolBar

現在我們來修改 activity_main.xml 中的代碼,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

       這段代碼不長,但裏面卻有不少技術點去仔細琢磨一下,首先看一下第三行,這裏使用 xmlns:app 指定了一個新的命名空間,思考一下,這是由於每個佈局文件都是用到 xmlns:android 來指定一個命名空間,因此我們才能一直使用 android:id、android:layout_width、android:layout_height 等寫法,那麼這裏指定了 xmlns:app,也就是說可以使用 xmlns:attribute 這樣的寫法了,但是這裏爲什麼要指定 xmlns:app 的命名空間呢,這是由於 Material Design 是在 Android 5.0 系統中才出現的,而很多的 Material 屬性在 5.0 之前系統中國並不存在,那麼爲了能夠兼容之前的老系統,我們就不能使用 android:attribute,而是使用 app:attribute

接下來定義了一個 Toolbar 控件,這個庫是由 appcompat-v7 庫提供的,這裏給控件加一個 id,寬指定爲 match_parent,高設置爲 actionBar 的高度,背景色設置爲 colorPrimary,這些都很好理解,接下來使用了 app:popupTheme 屬性,可以單獨將彈出的菜單項指定成淺色主題,之所以使用 app:popupTheme,是因爲這個屬性是 5.0 中新增的,我們使用 app:popupTheme 就可以兼容 5.0 以下的系統了

寫完佈局,接下來我們來修改 MainActivity 中的代碼,如下所示:

/**
 * ToolBar 練習
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar);
        setSupportActionBar(toolbar);
    }
}

這裏關鍵代碼只有兩句,主要就是通過調用 setSupportActionBar() 方法將 ToolBar 的實例傳入,這樣我們就做到了既使用 ToolBar,又讓它的外觀與功能和 ActionBar 一致了,運行一下程序,效果圖如下:





這個標題欄我們就太熟悉了,雖然看上去和之前的標題欄沒有兩樣,但它其實已經是 ToolBar 而不是 ActionBar 了,因此它現在也具備了實現 Material Design 效果的功能

接下來我們再看一下 ToolBar 常用的功能吧,比如修改標題欄上文字的顏色,以及顯示文字的內容,如下:

修改標題欄顏色:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

修改顯示文字,這裏給 Activity 增加了一個 android:label 屬性,用於指定 ToolBar 中顯示文字的內容,如果沒有指定的話,會默認顯示 application 中指定的 label 內容,也就是我們的應用名稱,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.qiudengjiao.materialdesign">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="你好"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

只有一個標題的 ToolBar 看起來太單調了,我們接下來添加一些按鈕,來讓 ToolBar 更加豐富一些,這裏我們直接拿系統自帶的圖標來顯示,現在我們在 res 文件夾下創建一個 menu 文件夾,然後右擊創建 toolbar.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/backup"
        android:icon="@mipmap/ic_launcher"
        android:title="Backup"
        app:showAsAction="always" />
    
    <item
        android:id="@+id/delete"
        android:icon="@mipmap/ic_launcher"
        android:title="Delete"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/setting"
        android:icon="@mipmap/ic_launcher"
        android:title="Setting"
        app:showAsAction="never" />

</menu>

可以看到,我們通過<item>標籤來定義 action 按鈕,這裏我們就是要注意一下 app:showAsAction 的用法,這個主要是用來指定按鈕顯示的位置,之所以這裏再次使用了 app 的命名空間,同樣是爲了能夠兼容低版本的系統,showAsAction 主要有三種值可選:
  • always 表示永遠顯示在 ToolBar 中,如果屏膜空間不夠則不顯示
  • ifRoom 表示屏膜空間足夠的情況下,顯示在 ToolBar 中,不夠的話就顯示在菜單當中,
  • naver 則表示永遠顯示在菜單當中
注意:ToolBar 中的 action 按鈕只會顯示圖標,菜單中的 action 按鈕只會顯示文字,接下來我們修改 MainActivity 中的代碼,如下所示:

/**
 * ToolBar 練習
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar);
        setSupportActionBar(toolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

            case R.id.backup:
                Toast.makeText(this, "Click Backup", Toast.LENGTH_LONG).show();
                break;
            case R.id.delete:
                Toast.makeText(this, "Click Delete", Toast.LENGTH_LONG).show();
                break;
            case R.id.setting:
                Toast.makeText(this, "Click Setting", Toast.LENGTH_LONG).show();
                break;
            default:
        }
        return true;
    }
}


非常簡單,我們在 onCreateOptionsMenu() 方法中加載了 toolbar.xml 這個菜單文件,然後再 onOptionsItemSelected() 方法中處理各個按鈕的點擊事件,現在重新運行一下程序:



可以看到,ToolBar 上面現在顯示了兩個 aciton 按鈕,這是因爲 Backup 指定的顯示位置是 always,Delete 按鈕指定的顯示位置是 ifRoom,而現在屏幕的顯示位置很充足,因此兩個按鈕都會顯示在 ToolBar 中,另外一個 Setting 按鈕由於指定的顯示位置是 never 所以不會顯示在 ToolBar 中,點擊一下最右邊的菜單按鈕來展開菜單項,你就能找到 Setting 按鈕了

當然我們還可以在xml文件中指定如下的內容:

  <android.support.v7.widget.Toolbar
        android:id="@+id/toolBar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        app:logo="@mipmap/ic_launcher"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:subtitle="@string/app_name"
        app:subtitleTextColor="#c69aec"
        app:titleTextColor="#f5f0f0" />

例如用 app:logo 來指定 app 的圖標,以及用 app:subtitle 來指定副標題,app:subtitleTextColor 來指定副標題的顏色等,效果如下:




好了 ToolBar 我們就寫到這裏了,當然 ToolBar 的功能遠遠比這裏說的要多,大家慢慢來開發更強大的 ToolBar 吧,這裏解析了最基礎的也是最重要的 ToolBar 入門知識,如有錯誤請指正

聲明:文章參考郭大神第一行代碼




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章