MDC-104 Android:Material 高级组件 (Kotlin)

1. 简介

logo_components_color_2x_web_96dp.png

Material Components (MDC) 有助于开发者实现 Material Design。MDC 是由一组 Google 工程师和用户体验设计人员倾心打造的,提供数十种精美实用的界面组件,可用于 Android、iOS、Web 和 Flutter.material.io/develop

在 Codelab MDC-103 中,您通过自定义 Material Components (MDC) 的颜色、高度和字体排版,设置了应用的样式。

Material Design 系统中的组件可执行一组预定义的任务,并具有某些特征(例如按钮)。不过,按钮不仅是用户执行操作的方式,还是形状、大小和颜色的视觉表达,可以让用户知道,按钮是可以互动的,并且轻触或点击后会触发一些行为。

Material Design 准则从设计人员的角度对组件进行了介绍,说明了可在各个平台上使用的多种基本功能,以及构成每个组件的结构性元素。例如,背景幕包含后层及其内容、前层及其内容、动作规则和显示选项。其中每个组件都可以根据每个应用的需求、用例和内容进行自定义。这些组件主要包括传统视图、控件,以及平台 SDK 的功能。

虽然 Material Design 准则列出了许多组件,但其中有些组件并不适用于可重用代码,因此您在 MDC 中找不到这些组件。您可以全部使用传统代码自行打造这些体验,为您的应用实现自定义样式。

构建内容

在本 Codelab 中,您将向 Shrine 添加背景幕。它会按类别过滤非对称网格中显示的商品。您将使用:

  • 形状
  • 动作
  • 传统的 Android SDK 类

21c025467527a18e.png dcde66003cd51a5.png

本 Codelab 中用到的 MDC-Android 组件

  • 形状

所需条件

  • 已掌握 Android 开发方面的基础知识
  • Android Studio(如果尚未安装,请在此处下载)
  • Android 模拟器或设备(可通过 Android Studio 获取)
  • 示例代码(参见下一步)

您如何评价自己在构建 Android 应用方面的经验水平?

新手水平 中等水平 熟练水平

2. 设置您的开发环境

接着 MDC-103 继续操作?

如果您已完成 MDC-103,您的代码应该就能用于本 Codelab 了。请跳到第 3 步。

从头开始?

下载起始 Codelab 应用

起始应用位于 material-components-android-codelabs-104-starter/kotlin 目录中。请务必先通过 cd 命令转到该目录,然后再开始操作。

…或从 GitHub 克隆

如需从 GitHub 克隆此 Codelab,请运行以下命令:

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 104-starter

在 Android Studio 中加载起始代码

  1. 在设置向导完成且系统显示 Welcome to Android Studio 窗口后,点击 Open an existing Android Studio project。找到您安装了示例代码的目录,然后依次选择 kotlin -> shrine(或在计算机上搜索 shrine),以打开 Shipping 项目。
  2. 等待 Android Studio 构建和同步项目,如 Android Studio 窗口底部的 activity 指示器所示。
  3. 此时,由于缺少 Android SDK 或构建工具,因此 Android Studio 可能会显示一些构建错误(如下所示)。按照 Android Studio 中的说明安装/更新这些内容,并同步您的项目。

KzoYWC1S7Se7yL8igi1vXF_mbVxAdl2lg5kb7RODrsVpEng0G6U3NK1Qnn0faBBZd2u71yMXioy9tD-7fv3NXvVO4N3EtMMeWDTmqBMMl6egd9R5uXX0T_SKmahbmRor3wZZHX0ByA

添加项目依赖项

项目需要一个 MDC Android 支持库的依赖项。您下载的示例代码应该已经列出了此依赖项,但您最好按照以下步骤操作,以确保万无一失。

  1. 转到 app 模块的 build.gradle 文件,并确保 dependencies 代码块包含 MDC Android 的依赖项:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (可选)如有必要,请修改 build.gradle 文件以添加以下依赖项,并同步项目。
dependencies {
    api 'com.google.android.material:material:1.1.0-alpha06'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:core:1.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:runner:1.2.0-alpha05'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05'
}

运行起始应用

  1. 确保“Run / Play”按钮左侧的 build 配置是 app。
  2. 按绿色的“Run / Play”按钮,以构建并运行该应用。
  3. 在 Select Deployment Target 窗口中,如果已有 Android 设备列在可用设备列表中,请跳至第 8 步。否则,请点击 Create New Virtual Device。
  4. 在 Select Hardware 屏幕中,选择一个手机设备(如 Pixel 2),然后点击 Next。
  5. 在 System Image 屏幕中,选择较新的 Android 版本,最好选择最高的 API 级别。如果相应版本尚未安装,请点击随即显示的 Download 链接,然后完成下载。
  6. 点击 Next。
  7. 在 Android Virtual Device (AVD) 屏幕上,让各项设置保持不变,然后点击 Finish。
  8. 从部署目标对话框中选择一个 Android 设备。
  9. 点击 Ok。
  10. Android Studio 会构建并部署该应用,然后自动在目标设备上将其打开。

大功告成!您应该会看到在您设备上运行的 Shrine 应用。

79eaeaff51de5719.png

3. 添加背景幕菜单

背景幕是应用最靠后的表面,显示在所有其他内容和组件的后面。它由两个表面组成:后层(用于显示操作和过滤器)和前层(用于显示内容)。您可以使用背景幕来显示互动信息和操作,例如导航或内容过滤器。

隐藏网格内容

在 shr_product_grid_fragment.xml 中,将 android:visibility="gone" 属性添加到 NestedScrollView,以暂时移除商品内容:

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:elevation="8dp"
   android:visibility="gone"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

我们将在此区域中安装背景幕。为避免在顶部应用栏与背景幕上显示的菜单内容之间显示分隔线,我们将对背景幕使用与顶部应用栏相同的颜色。

在 shr_product_grid_fragment.xml 中,将以下内容添加为根 FrameLayout 中的第一个元素,就放在 AppBarLayout 的前面:

shr_product_grid_fragment.xml

<LinearLayout
   style="@style/Widget.Shrine.Backdrop"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:gravity="center_horizontal"
   android:orientation="vertical"
   android:paddingTop="100dp"
   android:paddingBottom="100dp">

</LinearLayout>

在 styles.xml 中,添加以下代码:

styles.xml

<style name="Widget.Shrine.Backdrop" parent="">
   <item name="android:background">?attr/colorAccent</item>
</style>

干得好!您已在 Shrine 的界面中添加了精美的背景幕。接下来,我们将添加菜单。

添加菜单

菜单本质上是文本按钮的列表。我们将在此处添加一个。

在 res -> layout 目录中创建一个名为 shr_backdrop.xml 的新布局文件,并添加以下内容:

shr_backdrop.xml

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_featured_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_apartment_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_accessories_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_shoes_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_tops_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_bottoms_label" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_dresses_label" />

   <View
       android:layout_width="56dp"
       android:layout_height="1dp"
       android:layout_margin="16dp"
       android:background="?android:attr/textColorPrimary" />

   <com.google.android.material.button.MaterialButton
       style="@style/Widget.Shrine.Button.TextButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/shr_account_label" />

</merge>

使用 <include> 标记将此列表添加到您刚刚在 shr_product_grid_fragment.xml 中添加的 LinearLayout:

shr_product_grid_fragment.xml

<LinearLayout
   style="@style/Widget.Shrine.Backdrop"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:gravity="center_horizontal"
   android:orientation="vertical"
   android:paddingTop="88dp">

   <include layout="@layout/shr_backdrop" />
</LinearLayout>

构建并运行。您的主屏幕应如下所示:

a87a58e2ccddbae5.png

现在,我们已完成背景幕的设置。接下来,让我们来恢复之前隐藏的内容。

4. 添加形状

在本 Codelab 中对 Shrine 进行任何更改之前,主要商品内容位于最靠后的表面。在添加背景幕后,由于这个内容是显示在背景幕的前面,因此该内容现在更加突出了。

添加新层

我们应该再次显示商品网格层。请从 NestedScrollView 中移除 android:visibility="gone" 属性:

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:elevation="8dp"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

我们来设置前层的样式,让左上角显示一个缺口。Material Design 将这种类型的自定义项称为形状。Material 表面可以用不同的形状显示。形状为表面增加了重点和风格,可用于展现品牌形象。Material 形状可以有弧形或尖锐的角和角的两条边,以及任意数量的边;可以是对称的,也可以是不规则的。

添加形状

修改网格的形状。我们提供了自定义的形状背景,但这种形状只有在 Android Marshmallow 及更高版本上才能显示正确。因此,我们只能在 Android Marshmallow 及更高版本上的 NestedScrollView 上设置 shr_product_grid_background_shape 背景。首先,将 id 添加到 NestedScrollView,以便我们在代码中对其进行引用,如下所示:

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:id="@+id/product_grid"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:elevation="8dp"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

然后,在 ProductGridFragment.kt 中以编程方式设置背景。添加以下逻辑,以在 onCreateView() 的末尾(就在 return 语句之前)设置该背景:

ProductGridFragment.kt

// Set cut corner background for API 23+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
       view.product_grid.background = context?.getDrawable(R.drawable.shr_product_grid_background_shape)
}

最后,我们将更新 productGridBackgroundColor 颜色资源(自定义形状背景也会使用该资源),如下所示:

colors.xml

<color name="productGridBackgroundColor">#FFFBFA</color>

构建并运行:

9cf7a94091438011.png

我们已为 Shrine 的主要表面提供了采用自定义样式的形状。由于表面有高度,用户可以看到前方的白色层后面还有内容。我们接下来要添加动作,让用户可以看到那里的内容,也就是菜单。

5. 添加动画

动作是一种可以让应用生动起来的方式。动作可以热烈奔放,也可以舒缓轻柔,还可以介于两者之间。您使用的动作类型应当适合具体情况。应用于重复性、规律性操作的动作应轻柔,以免操作经常耗费过多时间。其他情况(比如用户首次打开应用时)则适合使用更加抢眼的动作,以便让用户了解如何使用您的应用。

向菜单按钮添加显现动作

该动作是指在正对面垂直向下移动的形状。我们已为您提供了一个点击监听器,用于在 NavigationIconClickListener.kt 中完成动作条的平移动画。我们可以在 ProductGridFragement 的 onCreateView()(负责设置工具栏的部分)中设置此点击监听器。请添加以下代码行,以在工具栏的菜单图标上设置点击监听器:

ProductGridFragment.kt

view.app_bar.setNavigationOnClickListener(NavigationIconClickListener(activity!!, view.product_grid))

该部分现在应如下所示:

ProductGridFragment.kt

// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
view.app_bar.setNavigationOnClickListener(NavigationIconClickListener(activity!!, view.product_grid))

构建并运行。按菜单按钮:

46a878bade66f821.png

再次按导航菜单图标应该能隐藏它。

调整前层的动作

动作是表达品牌的绝佳方式。我们来看看使用不同时间曲线时,显现动画是什么样的。

更新 ProductGridFragment.kt 中的点击监听器,以将插值器传递给导航图标的点击监听器,如下所示:

ProductGridFragment.kt

view.app_bar.setNavigationOnClickListener(NavigationIconClickListener(activity!!, view.product_grid, AccelerateDecelerateInterpolator()))

这会产生不同的效果,不是吗?

6. 品牌图标

品牌图标也可以扩大到我们熟悉的图标。接下来,我们要将显现图标设为自定义并将其与我们的标题合并,形成独特的品牌外观。

更改菜单按钮图标

更改菜单按钮以显示包含钻石设计的图标。更新 shr_product_grid_fragment.xml 中的工具栏,以使用我们为您提供的全新品牌图标 (shr_branded_menu),并设置 app:contentInsetStart 和 android:padding 属性,以便让工具栏更符合设计人员的规范:

shr_product_grid_fragment.xml

<androidx.appcompat.widget.Toolbar
   android:id="@+id/app_bar"
   style="@style/Widget.Shrine.Toolbar"
   android:layout_width="match_parent"
   android:layout_height="?attr/actionBarSize"
   android:paddingStart="12dp"
   android:paddingLeft="12dp"
   android:paddingEnd="12dp"
   android:paddingRight="12dp"
   app:contentInsetStart="0dp"
   app:navigationIcon="@drawable/shr_branded_menu"
   app:title="@string/shr_app_name" />

我们将再次更新 ProductGridFragment.kt 中 onCreateView() 的点击监听器,以便在菜单打开和关闭时接受工具栏的可绘制对象,如下所示:

ProductGridFragment .kt

// Set up the toolbar.
(activity as AppCompatActivity).setSupportActionBar(view.app_bar)
view.app_bar.setNavigationOnClickListener(NavigationIconClickListener(
       activity!!,
       view.product_grid,
       AccelerateDecelerateInterpolator(),
       ContextCompat.getDrawable(context!!, R.drawable.shr_branded_menu), // Menu open icon
       ContextCompat.getDrawable(context!!, R.drawable.shr_close_menu))) // Menu close icon

构建并运行:

21c025467527a18e.png dcde66003cd51a5.png

太棒了!当背景幕可以显现时,系统会显示钻石形状的菜单图标;当菜单可以隐藏时,系统会改为显示关闭图标。

7. 回顾

在学习这四个 Codelab 的过程中,您已经了解如何使用 Material Components 打造独特、优雅的用户体验,表现品牌的个性和风格。

后续步骤

我们已学完此 Codelab (MDC-104),本 Codelab 系列到此结束。您可以访问 MDC-Android 组件目录,探索 MDC-Android 中的更多组件。

如需完成此 Codelab 的进一步挑战,请修改您的 Shrine 应用,以更改从背景幕菜单中选择某个类别后显示的商品图片。

如需了解如何将此应用关联到 Firebase 以使用可正常工作的后端,请参阅 Firebase Android Codelab。

我能够用合理的时间和精力完成此 Codelab

非常赞同 赞同 中立 不赞同 非常不赞同

我希望日后继续使用 Material Components

非常同意 同意 一般 不同意 非常不同意