工具栏兼容性

概述

本部分介绍如何在 Android 5.0 Lollipop 之前的 Android 版本上使用 Toolbar。 如果应用不支持早于 Android 5.0 的 Android 版本,则可以跳过本部分。

由于 Toolbar 是 Android v7 支持库的一部分,因此可以在运行 Android 2.1(API 级别 7)及更高级别的设备上使用它。 但是,必须安装 Android 支持库 v7 AppCompat NuGet 并修改代码,以便它使用此库中提供的 Toolbar 实现。 本部分介绍如何安装此 NuGet,并从“添加第二个工具栏”修改 ToolbarFun 应用,使其在低于 Lollipop 5.0 的 Android 版本上运行。

修改应用以使用工具栏的 AppCompat 版本:

  1. 为应用设置最低版本和目标 Android 版本。

  2. 安装 AppCompat NuGet 包。

  3. 使用 AppCompat 主题而不是内置的 Android 主题。

  4. 修改 MainActivity,使其子类为 AppCompatActivity 而不是 Activity

以下各节详细介绍了上述每个步骤。

设置最低版本和目标 Android 版本

应用的目标框架必须设置为 API 级别 21 或更高版本,否则应用将无法正确部署。 如果在部署应用时看到“包 “tileModeX”中找不到属性“tileModeX”的资源标识符”,这是因为目标框架未设置为 Android 5.0(API 级别 21 - Lollipop) 或更高版本。

将目标框架级别设置为 API 级别 21 或更高版本,并将 Android API 级别项目设置设置为应用支持的最低 Android 版本。 有关设置 Android API 级别的详细信息,请参阅了解 Android API 级别。 在 ToolbarFun 示例中,最低 Android 版本设置为 KitKat(API 级别 4.4)。

安装 AppCompat NuGet 包

接下来,将 Android 支持库 v7 AppCompat 包添加到项目中。 在 Visual Studio 中,右键单击“引用”并选择“管理 NuGet 包...”。单击“浏览”并搜索“Android 支持库 v7 AppCompat”。 选择 Xamarin.Android.Support.v7.AppCompat 并单击 安装

在“管理 NuGet 包”中选定的 V7 Appcompat 包的屏幕截图

安装此 NuGet 后,如果其他几个 NuGet 软件包尚未安装,也会同时安装(例如 Xamarin.Android.Support.Animated.Vector.DrawableXamarin.Android.Support.v4,以及 Xamarin.Android.Support.Vector.Drawable)。 有关安装 NuGet 包的详细信息,请参阅演练:在项目中包括 NuGet

使用 AppCompat 主题和工具栏

AppCompat 库附带了多个 Theme.AppCompat 主题,这些主题可用于 AppCompat 库支持的任何 Android 版本。 ToolbarFun 示例应用主题派生自 Theme.Material.Light.DarkActionBar,该主题在低于 Lollipop 的 Android 版本中不可用。 因此,ToolbarFun 必须对该主题的 AppCompat 对应程序进行调整,以使用 Theme.AppCompat.Light.DarkActionBar。 此外,由于 Toolbar 在低于 Lollipop 的 Android 版本中不可用,因此必须使用 Toolbar 的 AppCompat 版本。 因此,布局必须使用 android.support.v7.widget.Toolbar 而不是 Toolbar

更新布局

编辑 Resources/layout/Main.axml,并将 Toolbar 元素替换为以下 XML:

<android.support.v7.widget.Toolbar
    android:id="@+id/edit_toolbar"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorAccent"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

编辑 Resources/layout/toolbar.xml,并将其内容替换为以下 XML:

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

请注意,?attr 值不再带有 android: 前缀(回想一下,? 表示法引用当前主题中的资源)。 如果此处仍使用 ?android:attr,Android 将从当前正在运行的平台而不是 AppCompat 库引用属性值。 由于此示例使用 AppCompat 库定义的 actionBarSize,因此会删除 android: 前缀。 同样,@android:style 更改为 @style,以便 android:theme 属性设置为 AppCompat 库中的主题,此处会使用 ThemeOverlay.AppCompat.Dark.ActionBar 主题,而不是 ThemeOverlay.Material.Dark.ActionBar

更新样式

编辑 资源/值/styles.xml,并将其内容替换为以下 XML:

<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <style name="MyTheme" parent="MyTheme.Base"> </style>
  <style name="MyTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="colorPrimary">#5A8622</item>
    <item name="colorAccent">#A88F2D</item>
  </style>
</resources>

此示例中的项名称和父主题不再带有 android: 前缀,因为我们使用的是 AppCompat 库。 此外,父主题更改为 Light.DarkActionBar 的 AppCompat 版本。

更新菜单

为了支持早期版本的 Android,AppCompat 库使用会镜像 android: 命名空间属性的自定义属性。 但是,某些属性(如 <menu> 标记中使用的 showAsAction 属性)在较旧的设备上不存在,showAsAction 是在 Android API 11 中引入的,但在 Android API 7 中不可用。 因此,必须使用自定义命名空间来为支持库定义的所有属性添加前缀。 在菜单资源文件中,定义了名为 local 的命名空间,用于为 showAsAction 属性添加前缀。

编辑 资源/菜单/top_menus.xml,并将其内容替换为以下 XML:

<?xml version="1.0" encoding="utf-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:local="http://schemas.android.com/apk/res-auto">
  <item
       android:id="@+id/menu_edit"
       android:icon="@mipmap/ic_action_content_create"
       local:showAsAction="ifRoom"
       android:title="Edit" />
  <item
       android:id="@+id/menu_save"
       android:icon="@mipmap/ic_action_content_save"
       local:showAsAction="ifRoom"
       android:title="Save" />
  <item
       android:id="@+id/menu_preferences"
       local:showAsAction="never"
       android:title="Preferences" />
</menu>

local 命名空间随以下行一起添加:

xmlns:local="http://schemas.android.com/apk/res-auto">

showAsAction 属性以此 local: 命名空间开头,而不是 android:

local:showAsAction="ifRoom"

同样,编辑 资源/菜单/edit_menus.xml,并将其内容替换为以下 XML:

<?xml version="1.0" encoding="utf-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:local="http://schemas.android.com/apk/res-auto">
  <item
       android:id="@+id/menu_cut"
       android:icon="@mipmap/ic_menu_cut_holo_dark"
       local:showAsAction="ifRoom"
       android:title="Cut" />
  <item
       android:id="@+id/menu_copy"
       android:icon="@mipmap/ic_menu_copy_holo_dark"
       local:showAsAction="ifRoom"
       android:title="Copy" />
  <item
       android:id="@+id/menu_paste"
       android:icon="@mipmap/ic_menu_paste_holo_dark"
       local:showAsAction="ifRoom"
       android:title="Paste" />
</menu>

此命名空间开关如何为 API 级别 11 之前的 Android 版本上的 showAsAction 属性提供支持? 安装 AppCompat NuGet 时,自定义属性 showAsAction 及其所有可能的值包含在应用中。

子类 AppCompatActivity

转换的最后一步是修改 MainActivity,以使它成为 AppCompatActivity 的子类。 编辑 MainActivity.cs 并添加以下 using 语句:

using Android.Support.V7.App;
using Toolbar = Android.Support.V7.Widget.Toolbar;

这声明 Toolbar 为 AppCompat 版本的 Toolbar。 接下来,更改 MainActivity 的类定义:

public class MainActivity : AppCompatActivity

若要将操作栏设置为 AppCompat 版本的 Toolbar,请将调用 SetActionBar 替换为 SetSupportActionBar。 在此示例中,标题也作了更改,以表明使用的是 Toolbar 的 AppCompat 版本:

SetSupportActionBar (toolbar);
SupportActionBar.Title = "My AppCompat Toolbar";

最后,将最低 Android 级别更改为要支持的 Lollipop 前值(例如 API 19)。

生成应用并在预 Lollipop 设备或 Android 仿真器上运行它。 以下屏幕截图显示了运行 KitKat 的 Nexus 4 上的 ToolbarFun AppCompat 版本(API 19):

在 KitKat 设备上运行的应用的完整屏幕截图,两个工具栏都处于显示状态

使用 AppCompat 库时,无需基于 AppCompat 库的 Android 版本切换主题,就可以在所有受支持的 Android 版本中提供一致的用户体验。