MDC-101 Flutter:Material 组件 (MDC) 基础知识 (Flutter)

什么是 Material Design 和适用于 Flutter 的 Material 组件?

Material Design 是一个用于构建醒目、美观的数字产品的系统。采用一套统一的原则和组件将风格、品牌、交互和动效结合起来,产品团队得以释放其极大的设计潜能。

适用于 Flutter 的 Material 组件 (MDC-Flutter) 将设计和工程与组件库结合在一起,从而在各种应用和平台之间打造一致的用户体验。随着 Material Design 系统的发展,这些组件会进行相应更新,以确保一致的像素级完美实现,并遵循 Google 的前端开发标准。MDC 同样适用于 Android、iOS 和网页。

在此 Codelab 中,您将使用 MDC Flutter 的若干组件构建一个登录页面。

构建内容

我们提供了 4 个 Codelab 来引导您构建一款名为 Shrine 的应用,这是其中的第 1 个 Codelab。Shrine 是一款销售服饰和家居用品的电子商务应用。此 Codelab 将演示如何使用 MDC-Flutter 自定义组件来体现任何品牌或风格。

在此 Codelab 中,您将为 Shrine 构建一个包含以下内容的登录页面:

  • Shrine 徽标的图片
  • 应用名称 (Shrine)
  • 两个文本字段,分别用于输入用户名和密码
  • 两个按钮

Android

iOS

此 Codelab 中用到的 MDC 组件

  • 文本字段
  • 按钮
  • 涟漪(对触摸事件的可视形式反馈)

您如何评价自己在 Flutter 开发方面的经验水平?

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

前期准备

如需开始使用 Flutter 开发移动应用,您需要执行以下操作:

  1. 下载并安装 Flutter SDK。
  2. 使用 Flutter SDK 更新您的 PATH。
  3. 安装带有 Flutter 和 Dart 插件的 Android Studio 或您喜欢使用的编辑器。
  4. 安装 Android 模拟器、iOS 模拟器(需要装有 Xcode 的 Mac)或使用实体设备。

如需详细了解 Flutter 安装说明,请参阅开始使用:安装。如需设置编辑器,请参阅开始使用:设置编辑器。安装 Android 模拟器时,您可以根据需要选择默认选项,例如带有最新系统映像的 Pixel 3 手机。建议启用虚拟机加速功能,但这并非强制要求。完成上述 4 个步骤后,您可以返回此 Codelab。您只需要为一个平台(Android 或 iOS)安装 Flutter 即可完成此 Codelab。

确保 Flutter SDK 的版本符合要求

在继续学习此 Codelab 之前,请确保 SDK 版本符合要求。如果 Flutter SDK 是之前安装的,请使用 flutter upgrade 确保 SDK 是最新版本。

 flutter upgrade

运行 flutter upgrade 将自动运行 flutter doctor.。如果此次是全新的 Flutter 安装,则无需升级,手动运行 flutter doctor 即可。它将报告您是否需要安装任何依赖项才能完成此安装操作。您可以忽略与您的情况无关的勾选项(例如,如果您不打算开发 iOS 应用,就可以忽略 Xcode)。

 flutter doctor

常见问题解答

下载入门项目

入门项目位于 material-components-flutter-codelabs-101-starter/mdc_100_series 目录中。

...或从 GitHub 克隆

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

git clone https://github.com/material-components/material-components-flutter-codelabs.git
cd material-components-flutter-codelabs/mdc_100_series
git checkout 101-starter

设置项目

以下说明假定您使用的是 Android Studio (IntelliJ)。

打开项目

1. 打开 Android Studio。

2. 如果您看到欢迎屏幕,请点击 Open an existing Android Studio project

3. 导航到 material-components-flutter-codelabs/mdc_100_series 目录并点击“Open”。此时项目应会打开。在构建一次项目之前,您可以忽略您在 Dart Analysis 中看到的任何错误。

4. 如果出现提示,请执行以下操作:

  • 安装所有的平台和插件更新或 FlutterRunConfigurationType。
  • 如果未配置 Dart 或 Flutter SDK,请设置 Flutter 插件的 Flutter SDK 路径
  • 配置 Android 框架。
  • 点击“Get dependencies”或“Run ‘flutter packages get'”。

然后重启 Android Studio。

运行入门版应用

以下说明假定您在 Android 模拟器或设备上测试,但如果您安装了 Xcode,则还可以在 iOS 模拟器或设备上进行测试。

1. 选择设备或模拟器。如果 Android 模拟器尚未运行,请依次选择 Tools -> Android -> AVD Manager创建虚拟设备并启动模拟器。如果 AVD 已存在,您可以直接从 Android Studio 中的设备选择器启动模拟器,如下一步所示。(对于 iOS 模拟器,如果它尚未运行,请依次选择 Flutter Device Selection -> Open iOS Simulator 在开发机器上启动模拟器。)

2. 启动 Flutter 应用:

  • 查看编辑器屏幕顶部的 Flutter Device Selection 下拉菜单,然后选择设备(例如,iPhone SE 或 Android SDK built for <版本>)。
  • Play 图标 ()。

大功告成!您的模拟器中现在应该正在运行 Shrine 登录页面的起始代码。您应该会看到 Shrine 徽标,并在徽标正下方看到其名称“Shrine”。

Android

iOS

我们来看一下代码。

login.dart 中的微件

打开 login.dart。其中应包含以下代码:

import 'package:flutter/material.dart';

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  // TODO: Add text editing controllers (101)
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ListView(
          padding: EdgeInsets.symmetric(horizontal: 24.0),
          children: <Widget>[
            SizedBox(height: 80.0),
            Column(
              children: <Widget>[
                Image.asset('assets/diamond.png'),
                SizedBox(height: 16.0),
                Text('SHRINE'),
              ],
            ),
            SizedBox(height: 120.0),
            // TODO: Wrap Username with AccentColorOverride (103)
            // TODO: Remove filled: true values (103)
            // TODO: Wrap Password with AccentColorOverride (103)
            // TODO: Add TextField widgets (101)
            // TODO: Add button bar (101)
          ],
        ),
      ),
    );
  }
}

// TODO: Add AccentColorOverride (103)

请注意,代码中包含一个 import 语句和两个新类:

  • import 语句用于将 Material 组件引入此文件。
  • LoginPage 类表示模拟器中显示的整个页面。
  • _LoginPageState 类的 build() 函数用于控制界面中所有微件的创建方式。

首先,我们将在登录页面中添加两个文本字段,供用户输入用户名和密码。我们将使用 TextField 微件,该微件将显示悬浮标签并激活触摸涟漪。

此页面主要采用 ListView 构造,ListView 在可滚动的列中排列其子项。我们将文本字段放在底部。

添加 TextField 微件

SizedBox(height: 120.0) 后添加两个新的文本字段和一个分隔符。

// TODO: Add TextField widgets (101)
// [Name]
TextField(
  decoration: InputDecoration(
    filled: true,
    labelText: 'Username',
  ),
),
// spacer
SizedBox(height: 12.0),
// [Password]
TextField(
  decoration: InputDecoration(
    filled: true,
    labelText: 'Password',
  ),
  obscureText: true,
),

每个文本字段都有一个 decoration: 字段,用于获取 InputDecoration 微件。filled: 字段表示文本字段的背景被浅色填充,以帮助用户识别文本字段的点按或触摸目标区域。第二个文本字段的 obscureText: true 值会自动将用户的输入替换为项目符号,适用于输入密码的位置。

保存执行热重载的项目(使用按键:command + s)。

您现在应会看到一个包含两个文本字段(Username 和 Password)的页面!查看悬浮标签动画:

Android

iOS

接下来,我们将向登录页面添加两个按钮:“Cancel”和“Next”。我们将使用两种 MDC 按钮微件:FlatButton(在 Material 准则中称为“文本按钮”)和 RaisedButton(称为“实心按钮”)。

添加 ButtonBar

在文本字段后面,将 ButtonBar 添加到 ListView 的子项:

// TODO: Add button bar (101)
ButtonBar(
  // TODO: Add a beveled rectangular border to CANCEL (103)
  children: <Widget>[
    // TODO: Add buttons (101)
  ],
),

ButtonBar 会将其子项排列成一行。

添加按钮

然后将两个按钮添加到 ButtonBar 的 children 列表中:

    // TODO: Add buttons (101)
    FlatButton(
      child: Text('CANCEL'),
      onPressed: () {
        // TODO: Clear the text fields (101)
      },
    ),
    // TODO: Add an elevation to NEXT (103)
    // TODO: Add a beveled rectangular border to NEXT (103)
    RaisedButton(
      child: Text('NEXT'),
      onPressed: () {
    // TODO: Show the next page (101)
      },
    ),

保存您的项目。在最后一个文本字段下方,您应该会看到两个按钮:

Android

iOS

ButtonBar 会为您处理布局工作。它会将按钮水平放置在一起,让它们根据当前 ButtonTheme 中的内边距依次显示。(如需了解详情,请参阅 Codelab MDC-103。)

现在触摸某个按钮会启动水墨涟漪动画,而不会引发其他任何事件。让我们为匿名 onPressed: 函数添加一些功能,使“Cancel”按钮能够清除文本字段,“Next”按钮可以关闭屏幕:

添加 TextEditingControllers

为了能够清除文本字段的值,我们将添加 TextEditingControllers 来控制其文本。

_LoginPageState 类的声明的正下方,将控制器添加为 final 变量。

  // TODO: Add text editing controllers (101)
  final _usernameController = TextEditingController();
  final _passwordController = TextEditingController();

在第一个文本字段的 controller: 字段中,设置 _usernameController

// [Name]
TextField(
  controller: _usernameController,

在第二个文本字段的 controller: 字段中,设置 _passwordController

// [Password]
TextField(
  controller: _passwordController,

编辑 onPressed

在 FlatButton 的 onPressed: 函数中添加命令以清除每个控制器:

    // TODO: Clear the text fields (101)
    _usernameController.clear();
    _passwordController.clear();

保存您的项目。现在,当您在文本字段中输入内容时,点击“Cancel”会再次清除每个字段。

此登录表单结构完善!让我们带领用户继续探索 Shrine 应用的其他部分。

弹出

为关闭此视图,我们希望从导航栈中弹出(或删除)此页面(在 Flutter 中称为路由)。

在 RaisedButton 的 onPressed: 函数中,从 Navigator 中弹出最近的路由:

        // TODO: Show the next page (101)
        Navigator.pop(context);

最后,打开 home.dart 并在 Scaffold 中将 resizeToAvoidBottomInset 设置为 false

    return Scaffold(
      // TODO: Add app bar (102)
      // TODO: Add a grid view (102)
      body: Center(
        child: Text('You did it!'),
      ),
      // TODO: Set resizeToAvoidBottomInset (101)
      resizeToAvoidBottomInset: false,
    );

这样做可确保键盘的外观不会更改首页或其微件的大小。

大功告成!保存项目。继续操作,点击“Next”。

大功告成!

Android

iOS

此屏幕是我们下一个 Codelab 的起点,您可以在 MDC-102 中继续使用它。

我们添加了文本字段和按钮,并且在过程中几乎不用考虑布局代码。适用于 Flutter 的 Material 组件提供很多样式,几乎可以毫不费力地布局到屏幕上。

后续步骤

文本字段和按钮是 Material 系统的两个核心组件,但该系统还提供了许多其他组件!您还可以在 Flutter 的 Material 组件库中探索其余微件。

或者,前往 MDC-102:Material Design 结构和布局,了解 MDC-102 所涵盖的 Flutter 组件。

下一个 Codelab

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

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

我希望日后继续使用 Material 组件

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