应用栏

最基本的操作栏会在一侧显示 Activity 的标题,在另一侧显示一个 溢出菜单

从 Android 3.0(API 级别 11)开始,所有使用默认主题的 Activity 均使用 ActionBar 作为应用栏。现已被 Toolbar 取代,以确保您的应用在最大范围的设备上保持一致的行为。

Toolbar 小部件能够在运行 Android 2.1(API 级别 7)或更高版本的设备上提供 Material Design 体验,但除非设备运行的是 Android 5.0(API 级别 21)或更高版本,否则原生操作栏不会支持 Material Design。

ActionBar 是固定在顶部,并不能移动,我觉得这是最大的不好,而我们的 ToolBar 可以让我们随便摆放,就就可以带来很多灵活性和效果啦!

本篇所使用到的程序请到 Github 取得。

向 Activity 添加工具栏

  1. 按照支持库设置中所述向您的项目添加 v7 appcompat 支持库。

    implementation com.android.support:appcompat-v7:24.2.0
    
  2. 确保 Activity 可以扩展 AppCompatActivity

    public class MyActivity extends AppCompatActivity {  
      // ...  
    }


**注**:请为您应用中每个使用 Toolbar 作为应用栏的 Activity 进行此更改。
  1. 在应用清单中,将 <application> 元素设置为使用 appcompat 的其中一个 NoActionBar 主题。使用这些主题中的一个可以防止应用使用原生 ActionBar 类提供应用栏。例如:
    <application  android:theme="@style/Theme.AppCompat.Light.NoActionBar"  />

以上这种方式,直接替换了整个应用的主题,有的时候这种手法过于残暴。我们可以修改当前主题来达到目的。

修改 `styles.xml` 文件中的 `<AppTheme>` 标签中,加入如下两行:

    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>

还可以选择通过将 AppTheme 的 parent 设置为 Theme.AppCompat.Light.NoActionBar 的方式。

为了之后设定方便,我们先在 res/values/styles.xml 里增加一个名为 AppTheme.Base 的风格

    <style name="AppTheme.Base" parent="Theme.AppCompat">
      <item name="windowActionBar">false</item>
      <item name="android:windowNoTitle">true</item>
    </style>

因为此范例只使用 Toolbar,所以我们要将让原本的 ActionBar 隐藏起来,然后将原本 AppTheme 的 parent 属性 改为上面的AppTheme.Base,代码如下:

    <resources>

      <!-- Base application theme. -->
      <style name="AppTheme" parent="AppTheme.Base">
      </style>

      <style name="AppTheme.Base" parent="Theme.AppCompat">
        <item name="windowActionBar">false</item>
        <del><item name="android:windowNoTitle">true</item></del>
        <!-- 使用 API Level 22 編譯的話,要拿掉前綴字 -->
        <item name="windowNoTitle">true</item>
      </style>

    </resources>

再来调整 Android 5.0 的style:/res/values-v21/styles.xml,也将其 parent 属性改为 AppTheme.Base:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <style name="AppTheme" parent="AppTheme.Base">
        </style>
    </resources>
  1. 向 Activity 的布局添加一个 Toolbar。例如,以下布局代码可以添加一个 Toolbar 并赋予其浮动在 Activity 之上的外观:

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

    Material Design 规范 建议应用栏具有 4 dp 的仰角。

    将工具栏定位在 Activity 布局的顶部,因为您要使用它作为应用栏。

    app:popupTheme 这个属性就是用来自定义我们弹出的菜单的样式,在之前的 Actionbar 的溢出菜单,我们是不能自定义他的样式的。app:popupTheme="ThemeOverlay.AppCompat.Light,那么这个 Overflow 弹出的是白底黑字。

  2. 在 Activity 的 onCreate() 方法中,调用 Activity 的 setSupportActionBar() 方法,然后传递 Activity 的工具栏。该方法会将工具栏设置为 Activity 的应用栏。例如:

    @Override
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_my);  
        Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);  
        setSupportActionBar(myToolbar);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    

您的应用现在具有一个基本操作栏。默认情况下,操作栏只包含应用的名称和一个溢出菜单。选项菜单最初只包含 Settings 菜单项。您可以按照 添加和处理操作 中所述向操作栏和溢出菜单添加更多操作。

使用应用栏实用方法

将工具栏设置为 Activity 的应用栏后,您就可以访问 v7 appcompat 支持库的 ActionBar 类提供的各种实用方法。您可以通过此方法执行许多有用的操作,例如隐藏和显示应用栏。

要使用 ActionBar 实用方法,请调用 Activity 的 getSupportActionBar() 方法。此方法将返回对 appcompat ActionBar 对象的引用。获得该引用后,您就可以调用任何一个 ActionBar 方法来调整应用栏。例如,要隐藏应用栏,请调用 ActionBar.hide()

添加和处理操作

添加向上操作

Adding an Up Action

操作视图和操作提供程序

Action Views and Action Providers

AppBarLayout

AppBarLayout 继承自 LinearLayout,布局方向为垂直方向。所以你可以把它当成垂直布局的LinearLayout来使用。AppBarLayout 是在 LinearLayou 上加了一些材料设计的概念,它可以让你定制当某个可滚动View的滚动手势发生变化时,其内部的子View实现何种动作。

请注意:上面提到的某个可滚动View,可以理解为某个 ScrollView。怎么理解上面的话呢?就是说,当某个ScrollView发生滚动时,你可以定制你的“顶部栏”应该执行哪些动作(如跟着一起滚动、保持不动等等)。那某个可移动的View到底是哪个可移动的 View 呢?这是由你自己指定的!如何指定,我们后面说。

See Material Design之 AppbarLayout 开发实践总结

自定义颜色(Customization color)

这个阶段将从 toolbar_demo_checkpoint1 接着往下进行:

上图是将本阶段要完成的结果画面做了标示,结合下面的描述希望大家能明白。

  1. colorPrimaryDark(状态栏底色):在风格 (styles) 或是主题 (themes) 里进行设定。

  2. App bar 底色。

    若你的 android app 仍是使用 actionbar ,则直接在风格 (styles) 或是主题 (themes) 里进行设定 colorPrimary 参数即可。可若是采用 toolbar 的话,则要在界面 (layout) 里面设定 toolbar 控件的 background 属性。

  3. navigationBarColor(导航栏底色)

    仅能在 API v21 也就是 Android 5 以后的版本中使用, 因此要将之设定在 res/values-v21/styles.xml 里面。

  4. 主视窗底色:windowBackground

也因此在这个阶段,我们需要设定的地方有三,一是 style中(res/values/styles.xml)

1
2
3
4
5
6
7
8
9
10
<style name="AppTheme.Base" parent="Theme.AppCompat">
<item name="windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<!-- Actionbar color -->
<item name="colorPrimary">@color/accent_material_dark</item>
<!--Status bar color-->
<item name="colorPrimaryDark">@color/accent_material_light</item>
<!--Window color-->
<item name="android:windowBackground">@color/dim_foreground_material_dark</item>
</style>

再来是 v21 的style中 (res/values-v21/styles.xml)

1
2
3
4
<style name="AppTheme" parent="AppTheme.Base">
<!--Navigation bar color-->
<item name="android:navigationBarColor">@color/accent_material_light</item>
</style>

最后,就是为了本篇的主角 – Toolbar 的 background 进行设定。

1
2
3
4
5
6
7
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
android:background="?attr/colorPrimary" >
</android.support.v7.widget.Toolbar>

在本范例中,toolbar 是设定来在 activity_main.xml,对其设定 background 属性: android:background=”?attr/colorPrimary” ,这样就可以使之延用 Actionbar 的颜色设定喽。
最后,再来看一下结果画面。

完整代码见: toolbar_demo_checkpoint2

控件 (component)

本阶段将从 toolbar_demo_checkpoint2 接续,在还未于 标签中,自行添加元件的 toolbar 有几个大家常用的元素可以使用,请先见下图:

Toolbar-Component-300x160.png
Toolbar-Component-300x160.png

大抵来说,预设常用的几个元素就如图中所示,接着就依序来说明之:

  1. setNavigationIcon 即设定 up button 的图标,因为 Material 的介面,在 Toolbar这里的 up button样式也就有別于过去的 ActionBar 哦。
  2. setLogo APP 的图标。
  3. setTitle 主标题。
  4. setSubtitle 副标题。
  5. setOnMenuItemClickListener 设定菜单各按鈕的动作。

先来看看菜单外的代码,在 MainActivity.java 中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
// App Logo
toolbar.setLogo(R.drawable.ic_launcher);
// Title
toolbar.setTitle("My Title");
// Sub Title
toolbar.setSubtitle("Sub title");
setSupportActionBar(toolbar);
// Navigation Icon 要設定在 setSupoortActionBar 才有作用
// 否則會出現 back button
toolbar.setNavigationIcon(R.drawable.ab_android);

这边要留意的是setNavigationIcon需要放在 setSupportActionBar之后才会生效。

菜单部分,需要先在res/menu/menu_main.xml左定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<menu 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"
tools:context=".MainActivity">
<item android:id="@+id/action_edit"
android:title="@string/action_edit"
android:orderInCategory="80"
android:icon="@drawable/ab_edit"
app:showAsAction="ifRoom" />
<item android:id="@+id/action_share"
android:title="@string/action_edit"
android:orderInCategory="90"
android:icon="@drawable/ab_share"
app:showAsAction="ifRoom" />
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
app:showAsAction="never"/>
</menu>

再回到MainActivity.java 中加入OnMenuItemClickListener 的监听者:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private Toolbar.OnMenuItemClickListener onMenuItemClick = new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
String msg = "";
switch (menuItem.getItemId()) {
case R.id.action_edit:
msg += "Click edit";
break;
case R.id.action_share:
msg += "Click share";
break;
case R.id.action_settings:
msg += "Click setting";
break;
}
if(!msg.equals("")) {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
return true;
}
};

将onMenuItemClick监听者设置给toolbar

1
2
3
4
5
6
setSupportActionBar(toolbar);
...
// Menu item click 的監聽事件一樣要設定在 setSupportActionBar 才有作用
toolbar.setOnMenuItemClickListener(onMenuItemClick);

和 setNavigationIcon 一样,需要將之设定在 setSupportActionBar 之后才有作用。执行上面的代码便会得到下面的界面。

完完整程序见:toolbar_demo_checkpoint3

总结

在这样的架构设计下,ToolBar直接成了Layout中可以控制的东西,相对于过去的actionbar来说,设计与可操控性大幅提升。

本文上面的解释中用到的完成代码:toolbar demo check point 0 ~ 4,请到Github 取得。

最后再附上一个界面上常用的属性说明图:

这里按照图中从上到下的顺序做个简单的说明:

  • colorPrimaryDark 状态栏背景色。在 style 的属性中设置。
  • textColorPrimary App bar 上的标题与更多菜单中的文字颜色。在 style 的属性中设置。
  • App bar 的背景色。Actionbar 的背景色设定在 style 中的 colorPrimary。Toolbar 的背景色在layout文件中设置background属性。
  • colorAccent 各控制元件(如:check box、switch 或是 radoi) 被勾选 (checked) 或是选定 (selected) 的颜色。 在 style 的属性中设置。
  • colorControlNormal 各控制元件的预设颜色。在 style 的属性中设置
  • windowBackground App 的背景色。 在 style 的属性中设置
  • navigationBarColor 导航栏的背景色,但只能用在 API Level 21 (Android 5) 以上的版本 在 style 的属性中设置

Reference