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 入门知识,如有错误请指正

声明:文章参考郭大神第一行代码




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