Android Toolbar的用法

Toolbar的强大之处在于,它不仅继承了ActionBar的所有功能,而且灵活性很高,可以配合其他控件来完成一些Material Design的效果,下面来具体的看一下.

首先你要知道,任何一个新建的项目,默认都是会显示ActionBar的,这个想必你已经见识过太多次了,那么这个ActionBar到底是从哪里来的呢?其实这是根据项目中指定的主题来显示的,打开AndroidManifest.xml文件看一下,如图:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    ...
</application>

可以看到,这里使用android.theme属性指定了一个AppTheme的主题,那么这个AppTheme又是在哪里定义的呢?打开res/values/styles.xml文件,代码如下:

<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.DarkActionBar,这个DarkActionBar是一个深色的ActionBar主题,我们之前所有的项目中自带的ActionBar就是因为指定了这个主题才出现的,

而现在我们准备使用Toolbar来代替ActionBar,因此需要指定一个不带ActionBar的主题,通常有Theme.APPCompat.NoActionBar和Theme.APPCompat.Light.NoActionBar这两种主图可选,其中Theme.APPCompat.NoActionBar表示深色主题,它会将界面的主体颜色设成深色,陪衬颜色设成淡色,而Theme.APPCompat.Light.NoActionBar表示淡色主体,它会将界面的主体颜色设成淡色,陪衬颜色设成深色,这里我选择用淡色主题了,如下所示:

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- 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中的属性重写,这里重写了colorPrimary,colorPrimaryDark和colorAccent这3个属性的颜色,除了这3个属性之外,我们还可以通过textColorPrimary,windowBackground和navigationBarColor等属性来控制更多位置的颜色,不过唯独colorAccent这个属性比较难理解,它不只是用来指定这样一个按钮的颜色,而是更多表达了一个强调的意思,比如一些控件的选中状态也会使用colorAccent的颜色.

现在我们已经将ActionBar隐藏起来了,那么接下来看一看如何使用Toolbar来代替ActionBar,activity_main.xml中的代码,如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.toolbartest.MainActivity">

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

</android.support.constraint.ConstraintLayout>

接下来是MainActivity.Java中的代码,如下:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
}

首先通过findViewById()得到Toolbar的实例,然后调用setSupportActionBar()方法将Toolbar的实例传入,这样我们就做到即使用了Toolbar,又让它的外观与功能都能和ActionBar一致了.

现在运行一下程序,如图:

Android Toolbar的用法

这个标题栏我们再熟悉不过了,虽然看上去和之前的标题没什么两样,但其实它已经是Toolbar而不是ActionBar了,因此它现在也具备了实现Material Design效果的能力.

现在我们再看一下Toolbar比较常用的功能,比如修改标题上显示的文字内容,这段文字内容是在AndroidManifest,xml中指定的,如下:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity"
        android:label="Fruits">
        ...
    </activity>
</application>

这里给activity增加了一个android:label属性,用于指定在Toolbar中显示的文字内容,如果没有指定的话,会默认使用application中指定的label内容,也就是我们的应用名称.

不过只有一个标题的Toolbar看起来太单调了,我们还可以再添加一些action按钮来让Toolbar更加丰富一些,这里我提前准备了几张图片来作为按钮的图标,将它们放在了drawable目录下,现在右击res目录-->New-->Directory,创建一个menu文件夹,然后右击menu文件夹-->New-->Menu resource file,创建一个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="@drawable/ic_backup"
        android:title="Backup"
        app:showAsAction="always" />

    <item
        android:id="@+id/delete"
        android:icon="@drawable/ic_delete"
        android:title="Delete"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/settings"
        android:icon="@drawable/ic_settings"
        android:title="Settings"
        app:showAsAction="never" />

</menu>

可以看到,我们通过<item>标签来定义action按钮,android:id用于指定按钮的id,android:icon用于指定按钮的图片,android:title用于指定按钮的文字.

接着使用app:showAsAction来指定按钮的显示位置,之所以这里再次使用了app命名空间,同样是为了能够兼容低版本的系统,showAsAction主要有以下几种值可选,always表示永远显示在Toolbar中,如果屏幕空间不够则不显示,ifRoom表示屏幕空间足够的情况下显示在Toolbar中,不够的话就显示在菜单当中,never则表示永远显示在菜单当中,注意,Toolbar中的action按钮只会显示图标,菜单中的action按钮只会显示文字.

接下来修改MainActivity中的代码,如下:

public class MainActivity extends AppCompatActivity {

    ...
    
    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,"You clicked Backup",Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
                break;
                default:
                    break;
        }
        return true;
    }
}

很简单,我们在onCreateOptionMenu()方法中加载了toolbar.xml这个菜单文件,然后在onOptionsItemSelected()方法中处理各个按钮的点击事件,现在重新运行一下,效果如图:

Android Toolbar的用法

可以看到,Toolbar上面现在显示了两个action按钮,这是因为Backup按钮指定的显示位置是always,Delete按钮指定的显示位置是ifRoom,而现在屏幕空间很充足,因此两个按钮都会显示在Toolbar中,另外一个Settings按钮由于指定的显示位置是never,所以不会显示在Toolbar中,点击最右边的菜单按钮来展示菜单项,你就能找到Settings了.