1. 简介
Material Components (MDC) 有助于开发者实现 Material Design。MDC 是由一组 Google 工程师和用户体验设计人员倾心打造的,提供数十种精美实用的界面组件,可用于 Android、iOS、Web 和 Flutter.material.io/develop |
在 Codelab MDC-103 中,您自定义了 Material 组件 (MDC) 的颜色、高度和排版,以设置应用的样式。
Material Design 系统中的组件可执行一组预定义的任务,并具有某些特征(例如按钮)。不过,按钮不仅是用户执行操作的方式,还是形状、大小和颜色的视觉表达,可以让用户知道,按钮是可以互动的,并且轻触或点击后会触发一些行为。
Material Design 准则从设计人员的角度对组件进行了介绍,说明了可在各个平台上使用的多种基本功能,以及构成每个组件的结构性元素。例如,背景幕包含后层及其内容、前层及其内容、动作规则和显示选项。其中每个组件都可以根据每个应用的需求、用例和内容进行自定义。这些组件主要包括传统视图、控件,以及平台 SDK 的功能。
虽然 Material Design 准则列出了许多组件,但其中有些组件并不适用于可重用代码,因此您在 MDC 中找不到这些组件。您可以全部使用传统代码自行打造这些体验,为您的应用实现自定义样式。
构建内容
在本 Codelab 中,您将向 Shrine 添加背景幕。它会按类别过滤非对称网格中显示的商品。您将使用:
- 形状
- 动作
- 传统的 Android SDK 类
本 Codelab 中用到的 MDC-Android 组件
- 形状
所需条件
- 已掌握 Android 开发方面的基础知识
- Android Studio(如果尚未安装,请在此处下载)
- Android 模拟器或设备(可通过 Android Studio 获取)
- 示例代码(参见下一步)
您如何评价自己在构建 Android 应用方面的经验水平?
<ph type="x-smartling-placeholder">2. 设置您的开发环境
接着 MDC-103 继续操作?
如果您已完成 MDC-103,您的代码应该就能用于本 Codelab 了。请跳到第 3 步。
从头开始?
下载起始 Codelab 应用
起始应用位于 material-components-android-codelabs-104-starter/java
目录中。请务必先通过 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 中加载起始代码
- 在设置向导已完成且系统显示 Welcome to Android Studio 窗口后,点击 Open an existing Android Studio project。导航到安装了示例代码的目录,然后选择 java ->Shrine(或在计算机中搜索 shrine),以打开 Shrine 项目。
- 稍等片刻,让 Android Studio 构建和同步项目,如 Android Studio 窗口底部的 activity 指示器所示。
- 此时,由于缺少 Android SDK 或构建工具,因此 Android Studio 可能会显示一些构建错误(如下所示)。按照 Android Studio 中的说明安装/更新这些内容,并同步您的项目。
添加项目依赖项
项目需要一个 MDC Android 支持库的依赖项。您下载的示例代码应该已经列出了此依赖项,但您最好按照以下步骤操作,以确保万无一失。
- 转到
app
模块的build.gradle
文件,并确保dependencies
代码块包含 MDC Android 的依赖项:
api 'com.google.android.material:material:1.1.0-alpha06'
- (可选)如有必要,请修改
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' }
运行起始应用
|
大功告成!您应该会看到在您设备上运行的 Shrine 应用。
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>
构建并运行。您的主屏幕应如下所示:
背景幕创建完毕。接下来,让我们来恢复之前隐藏的内容。
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.java
中以编程方式设置背景。添加以下逻辑,以在 onCreateView()
的末尾(就在 return 语句之前)设置该背景:
ProductGridFragment.java
// Set cut corner background for API 23+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view.findViewById(R.id.product_grid).setBackgroundResource(R.drawable.shr_product_grid_background_shape);
}
最后,我们将更新 productGridBackgroundColor
颜色资源(自定义形状背景也会使用该资源),如下所示:
colors.xml
<color name="productGridBackgroundColor">#FFFBFA</color>
构建并运行:
我们已为 Shrine 的主要表面提供了采用自定义样式的形状。由于表面有高度,用户可以看到前方的白色层后面还有内容。我们接下来要添加动作,让用户可以看到那里的内容,也就是菜单。
5. 添加动画
动作是一种可以让应用生动起来的方式。动作可以热烈奔放,也可以舒缓轻柔,还可以介于两者之间。您使用的动作类型应当适合具体情况。应用于重复性、规律性操作的动作应轻柔,以免操作经常耗费过多时间。还有一些情况(如用户第一次打开应用)可能更加引人注目,并且有助于指导用户如何使用您的应用。
向菜单按钮添加显现动作
该动作是指在正对面垂直向下移动的形状。我们已为您提供了一个点击监听器,用于在 NavigationIconClickListener.java
中完成动作条的平移动画。我们可以在 ProductGridFragment.java
的 setupToolbar()
方法中设置此点击监听器:
ProductGridFragment.java
toolbar.setNavigationOnClickListener(new NavigationIconClickListener(getContext(), view.findViewById(R.id.product_grid)));
您的 setUpToolbar()
方法现在应如下所示:
ProductGridFragment.java
private void setUpToolbar(View view) {
Toolbar toolbar = view.findViewById(R.id.app_bar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
if (activity != null) {
activity.setSupportActionBar(toolbar);
}
toolbar.setNavigationOnClickListener(new NavigationIconClickListener(getContext(), view.findViewById(R.id.product_grid)));
}
构建并运行。按菜单按钮:
再次按导航菜单图标应该能隐藏菜单。
调整前层的动作
动作是表达品牌的绝佳方式。我们来看看使用不同时间曲线时,显现动画是什么样的。
在 ProductGridFragment.java
中更新 setupToolbar()
中的代码,以将插值器传递给导航图标的点击监听器,如下所示:
ProductGridFragment.java
private void setUpToolbar(View view) { Toolbar toolbar = view.findViewById(R.id.app_bar); AppCompatActivity activity = (AppCompatActivity) getActivity(); if (activity != null) { activity.setSupportActionBar(toolbar); } toolbar.setNavigationOnClickListener(new NavigationIconClickListener( getContext(), view.findViewById(R.id.product_grid), new 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.java
中 setupToolbar()
的点击监听器,以便在菜单打开和关闭时接受工具栏的可绘制对象,如下所示:
ProductGridFragment.java
private void setUpToolbar(View view) { Toolbar toolbar = view.findViewById(R.id.app_bar); AppCompatActivity activity = (AppCompatActivity) getActivity(); if (activity != null) { activity.setSupportActionBar(toolbar); } toolbar.setNavigationOnClickListener(new NavigationIconClickListener( getContext(), view.findViewById(R.id.product_grid), new AccelerateDecelerateInterpolator(), getContext().getResources().getDrawable(R.drawable.shr_branded_menu), // Menu open icon getContext().getResources().getDrawable(R.drawable.shr_close_menu))); // Menu close icon }
构建并运行:
太棒了!当背景幕可以显现时,系统会显示钻石形状的菜单图标;当菜单可以隐藏时,系统会改为显示关闭图标。
7. 要点回顾
在学习这四个 Codelab 的过程中,您已经了解如何使用 Material 组件打造独特、精巧的用户体验,展现品牌的个性和风格。
后续步骤
我们已学完此 Codelab (MDC-104),本 Codelab 系列到此结束。您可以访问 Android 微件目录,探索 MDC-Android 中的更多组件。
如需完成此 Codelab 的进一步挑战,请修改您的 Shrine 应用,以更改从背景幕菜单中选择某个类别后显示的商品图片。
如需了解如何将此应用与 Firebase 相关联,以使用有效的后端,请参阅 Firebase Android Codelab。