Material Design 意在为你构建一个大胆而且美观的数字产品设计系统。将风格、品牌、交互、动效通过统一的准则结合,发掘产品最大的设计潜力。
Flutter 的 Material 组件(MDC - Flutter)通过在应用间和平台间提供一个统一的用户体验组件库,把设计和工程合二为一。秉承着 Google 的前端开发标准,Material Design 系统正在向多端一致体验、像素级完美呈现的方向发展。Material Design 组件(MDC)也同样适用于 Android、iOS 和 Web。
在本 Codelab 里,你将使用 MDC - Flutter 的几个组件构建一个登录页面。
我们最终会构建一个售卖衣服和家居的电子商务应用 - Shrine,总共用四个 Codelab 来搞定它,本 Codelab 是其中的第一个,我们将带你一起使用 MDC - Flutter 来定制组件样式,以突显和匹配自身的品牌效果。
在本节,你将为 Shrine 应用构建一个登录页面,包含:
相关的 Codelabs 如下: | 在 MDC Flutter 教程 4 结束时,你将有机会做出一个这样的应用: |
你需要安装两部分来完成本次实验,Flutter 的 SDK 和编辑器(editor),这个 codelab 里,我们以 Android Studio 作为编辑器(editor),但你可以用个人更顺手的编辑器。
你可以通过如下任何设备完成本 codelab:
本项目位于 material-components-flutter-codelabs-101-starter/mdc_100_series
目录。
使用以下命令从 GitHub 克隆此 Codelab 所需的起步应用:
git clone https://github.com/material-components/material-components-flutter-codelabs.git cd material-components-flutter-Codelabs git checkout 101-starter
设置你的工程
如下设置工程的方法是使用 Android Studio 做演示的。
1. 在你的命令行工具里,切换到这个文件夹 | |
2. 执行命令 |
1. 打开 Android Studio | |
2. 当你看到欢迎界面时候,选择打开一个已存在的工程(Open an existing Android Studio project.) | |
3. 打开这个文件夹 如果此时提示一些错误请忽略,等第一次成功编译之后应该会好一些。 | |
4. 在项目面板左侧,删除测试文件 | |
5. 如果提示"升级平台和插件"或要配置 FlutterRunConfigurationType,请重启 Android Studio。 |
运行起步应用
下面我们以在 Android 模拟器或真机上为例做如下的步骤示范,当然如果你装有 Xcode,你也可以在 iOS 模拟器或真机上进行尝试。
1. 选择设备或模拟器 如果 Android 模拟器还没有运行起来,请选择 Tools -> Android -> AVD Manager 先进行 创建并启动模拟器 的操作。如果 AVD 里已经有创建好的模拟器,你可以直接在 IntelliJ 的设备选择列表里启动模拟器,如下一步所示。 (对于 iOS 模拟器,如果你还没有启动,请在你的电脑上选择 Flutter Device Selection -> Open iOS Simulator 来启动。) | |
2. 运行你的 Flutter 应用:
|
成功了!包含 Shrine 登录页面的起步代码已经在你的模拟器里跑起来了。你可以看到 Shrine 的 logo ,下面是它的名字 "SHRINE"。
让我们来看一下代码。
login.dart 中的 Widgets
打开 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()
方法里创建了显示所需要的所有 widget首先我们将为登录页面添加两个文本框,用于用户输入用户名和密码。我们会用到 TextField widget,它有一个悬浮的标签,并有触摸波纹效果。
这个页面主要由一个 ListView 组成,它将其子项排列在一个可滚动的列中。让我们把文本框放到底部。
添加两个新文本框,并通过 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 widget 。其中 filled
指该文本框的背景将被一个浅色填充,以助于用户分辨出点击或触摸区域。第二个文本框中 obscureText: true
是指将用户的输入自动替换为星号,一般用于密码文本框。
保存项目,会自动触发热重载功能。
现在你应该看到 Username 和 Password 两个文本框了!查看一下它们的悬浮标签和 ink 波纹效果:
接下来,我们将为登录页面添加两个按钮:"Cancel" 和 "Next" 。我们将使用两种 MDC 按钮 widget :FlatButton (在 Material Guidelines 中称为 "Text Button" )和 RaisedButton (也称 "Contained Button" )。
在文本框之后 ,向 ListView
的子项中添加 ButtonBar
。
// TODO: Add button bar (101)
ButtonBar(
// TODO: Add a beveled rectangular border to CANCEL (103)
children: <Widget>[
// TODO: Add buttons (101)
],
),
ButtonBar 把子项排列为一行。
然后,向 ButtonBar 的子项列表添加两个按钮:
// 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)
},
),
保存项目。在后一个文本框的下面,你应该看到出现了两个按钮。
ButtonBar 来为你处理布局。它将按钮水平放置,按钮们会按照当前的 ButtonTheme (你将在 Codelab MDC-103 中了解更多关于它的知识)依次排列。
触碰按钮会触发一次 ink 波纹效果,但目前仅限于此。让我们来给匿名的 onPressed
方法加上功能代码,让 Cancel 按钮来清除文本框,让 Next 按钮可以退出界面:
为了实现清除文本框内容,我们需要添加 TextEditingControllers 来控制文本。
在 _LoginPageState
类的开头 ,创建 controller 变量,并声明为 final 类型 。
// TODO: Add text editing controllers (101)
final _usernameController = TextEditingController();
final _passwordController = TextEditingController();
在第一个 TextField
中增加 controller: _usernameController
:
// [Name]
TextField(
controller: _usernameController,
在第二个 TextField
中增加 controller: _passwordController
:
// [Password]
TextField(
controller: _passwordController,
在 FlatButton 的 onPressed
方法中添加代码,让两个 controller
清空各自的文本内容:
// TODO: Clear the text fields (101)
_usernameController.clear();
_passwordController.clear();
保存项目。现在当你在文本框中输入了内容后,点击 Cancel 就会把内容都清空掉了。
这个登录表单看起来还不错!接下来我们来让用户可以进入到 Shrine 的其他页面吧。
要退出当前页面,我们要把这一页( Flutter 称为一个 route )从 navigation 栈中出栈(或者移除)。
在 RaisedButton 的 onPressed
方法中,将 Navigator 里最新加入的 route 出栈:
// TODO: Show the next page (101)
RaisedButton(
child: Text('NEXT'),
onPressed: () {
Navigator.pop(context);
},
),
保存项目。点击 "Next" 试一下。
是的,你完成了!
这一界面是我们下一个 Codelab 的起始点,你会在 MDC-102 中遇到它。
我们添加了文本框和按钮,并且几乎不用考虑布局。Flutter Material 组件带有许多样式,而且布局几乎毫不费力。
文本框和按钮是 Material 体系的两个核心组件,除此之外还有很多其他的组件!可以访问 widgets in Flutter's Material Components library 进一步探索。
或者你也可以前往 MDC-102: Material Design Structure and Layout 来学习 Flutter MDC-102 中所涉及的组件。