1. 简介
Flutter 是 Google 的界面工具包,用于通过单一代码库为移动、网络和桌面设备构建本机编译的精美应用。Flutter 可与现有代码一起使用,已受到全球开发者和组织的青睐,是免费的开放源代码。
在本 Codelab 中,您将扩展基本的 Flutter 移动应用以添加交互性。您还将创建用户可以导航前往的另一个页面(我们将其称为路由)。最后,您将修改应用的主题背景(颜色)。本 Codelab 是第 1 部分的后续内容, 在第 1 部分中,您创建了无限延迟加载的列表,但如果您要从第 2 部分开始,我们将提供初始代码。
您将在第 2 部分中学习的内容
- 如何编写像 iOS、Android 和 Web 原生应用一样的 Flutter 应用
- 如何使用热重载实现更短的开发周期
- 如何在有状态微件中添加交互性
- 如何创建并导航至另一个屏幕
- 如何使用主题背景更改应用外观
您将在第 2 部分中构建的内容
您将一个简单的移动应用开始,该应用用于为初创公司生成包含建议名称的无限列表。在本 Codelab 结尾,您的最终用户可以选择和取消选择名称,从而保留最佳名称。轻按应用栏右上方的列表图标可导航至一个新页面(称为路由),其中仅会列出已收藏的名称。
下方的动画 GIF 展示的是已完成应用的工作方式。
您想要从本 Codelab 中学到什么?
2. 设置您的 Flutter 环境
如果您未完成第 1 部分,请参阅 编写您的第一个 Flutter 应用(第 1 部分)中的 设置您的 Flutter 环境,以针对 Flutter 开发设置环境。
3. 获取起始应用
如果您完成了本 Codelab 的第 1 部分,则已拥有起始应用 startup_namer。可以继续完成下一步。
如果您没有 startup_namer,也无需担心,您可以使用下面的说明获取该应用。
使用 创建应用中的说明来创建简单的模板化 Flutter 应用。将此项目命名为 startup_namer
(而不是 flutter_app
)。
从 lib/main.dart
中删除所有代码。将代码替换为 本文件中的代码,该代码将显示包含初创公司建议名称的无限延迟加载列表。
通过添加英文单词软件包来更新 pubspec.yaml
:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
english_words: ^3.1.5 // NEW
此英文单词软件包会生成用作潜在初创公司名称的多对随机单词。
在 Android Studio 的编辑器视图中查看 pubspec 时,点击右上方的 Pub get,即可将软件包提取到您的项目中。您应该能在控制台中看到以下内容:
flutter pub get
Running "flutter pub get" in startup_namer...
Process finished with exit code 0
运行应用。
根据您的需要向下滚动,查看接连出现的初创公司建议名称。
4. 将图标添加到列表中
在此步骤中,您需要向每一行中添加心形图标。在下一步中,将其设置为可点按并保存收藏夹。
将 _saved
Set
添加到 _RandomWordsState
中。此 Set
可用于存储用户已收藏的单词对。Set
优于 List
,因为正确实现的 Set
不允许出现重复条目。
class _RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _saved = Set<WordPair>(); // NEW
final _biggerFont = TextStyle(fontSize: 18.0);
...
}
在 _buildRow
函数中,添加 alreadySaved
复选框,以确保系统尚未将单词对添加到收藏夹中。
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair); // NEW
...
}
在 _buildRow()
中,还需要将心形图标添加到 ListTile
对象中,以启用收藏功能。 在下一步中,您需要添加用于和心形图标交互的功能。
在文本后添加图标,如下方所示:
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon( // NEW from here...
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
), // ... to here.
);
}
热重载该应用。
您现在应该可在每一行上看到空心的心形图标,但其尚不具备交互性。
Android | iOS |
遇到了问题?
如果您的应用无法正常运行,则可通过使用以下链接中的代码恢复正常状态。
5. 添加交互性
在此步骤中,您需要将心形图标设置为可点按内容。当用户点按列表中的某个条目来切换其已收藏状态时,系统会在一组已保存的收藏项中添加或移除该单词配对。
如要执行此操作,您需要修改 _buildRow
函数。如果某个单词条目已添加到收藏夹中,则再次点按该条目,系统会将其从收藏夹中移除。当用户点按某个卡片时,该函数会调用 setState()
告知框架状态已更改。
将 onTap
添加到 _buildRow
方法中,如下所示:
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: () { // NEW lines from here...
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
}, // ... to here.
);
}
热重载该应用。
您应该能够点按任何卡片对条目进行收藏或取消收藏。点按卡片会从触碰点处生成隐式溅墨动画。
Android | iOS |
遇到了问题?
如果您的应用无法正常运行,则可通过使用以下链接中的代码恢复正常状态。
6. 导航至新屏幕
在此步骤中,您需要添加一个用于显示收藏夹的新页面(在 Flutter 中称为路由)。您将学习如何在主路由和新路由之间进行导航。
在 Flutter 中,Navigator
可用于管理包含应用路由的堆栈。将路由推送到 Navigator
的堆栈中会将显示内容更新为该路由。从 Navigator
的堆栈中弹出路由会令显示内容变为上一个路由。
接下来,将列表图标添加到 _RandomWordsState
的 build
方法的 AppBar
中。当用户点击列表图标时,系统会将包含已保存的收藏项的新路由推送到 Navigator
,以显示该图标。
将图标及其相应的操作添加到 build
方法中:
class _RandomWordsState extends State<RandomWords> {
...
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Startup Name Generator'),
actions: [
IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
],
),
body: _buildSuggestions(),
);
}
...
}
将 _pushSaved()
函数添加到 _RandomWordsState
类中。
void _pushSaved() {
}
热重载该应用。列表图标 将出现在应用栏中。由于 _pushSaved
函数为空,所以点按该图标暂时不会执行任何操作。
接下来,将构建路由并将其推送到 Navigator
的堆栈中。该操作可将显示内容更改为显示新路由。新页面的内容由系统在匿名函数中,使用 MaterialPageRoute
的 builder
属性构建而成。
调用 Navigator.push
(如下所示),这会将路由推送到 Navigator 的堆栈。IDE 将向您告知存在无效代码,但您将在下一节中解决此问题。
void _pushSaved() {
Navigator.of(context).push(
);
}
接下来,您需要添加 MaterialPageRoute
及其构建器。现在,添加用于生成 ListTile
行的代码。ListTile
的 divideTiles()
方法会在每个 ListTile
之间添加水平间距。divided
变量可负责保存由便利函数 toList()
转换为列表的最终行。
添加节点,如以下代码段中所示:
void _pushSaved() {
Navigator.of(context).push(
MaterialPageRoute<void>(
// NEW lines from here...
builder: (BuildContext context) {
final tiles = _saved.map(
(WordPair pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
);
},
);
final divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();
return Scaffold(
appBar: AppBar(
title: Text('Saved Suggestions'),
),
body: ListView(children: divided),
);
}, // ...to here.
),
);
}
}
builder
属性会返回 Scaffold
,其中包含新路由 SavedSuggestions
的应用栏。新路由的主体由包含 ListTiles
行的 ListView
组成。系统会在每行间,使用一个分隔线进行分隔。
热重载该应用。将一些所选项添加到收藏夹并点按应用栏中的列表图标。系统将显示包含收藏夹的新路由。请注意,Navigator 会将"返回"按钮添加到应用栏中。您不必显式实现 Navigator.pop
。点按"back"(返回)按钮即可返回到主路由。
iOS - 主路由 | iOS - 已保存的建议路由 |
遇到了问题?
如果您的应用无法正常运行,则可通过使用以下链接中的代码恢复正常状态。
7. 使用主题背景更改界面
在此步骤中,您需要修改应用的主题背景。主题背景会负责控制应用的外观。您可以使用默认主题背景(视实体设备或模拟器而定),也可以自定义主题背景以反映您的品牌。
您可通过配置 ThemeData
类来轻松更改应用的主题背景。应用会使用默认主题背景,但您需将该应用的主色更改为白色。
在 MyApp
类中更改颜色:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
theme: ThemeData( // Add the 3 lines from here...
primaryColor: Colors.white,
), // ... to here.
home: RandomWords(),
);
}
}
热重载该应用。包括应用栏在内的整个背景现在均为白色。
作为练习,请使用 ThemeData
更改界面的其他方面。您可从 Material 库的 Colors
类中, 获取可供试用的多种颜色常量。通过热重载,您可以快速、轻松地尝试使用界面。
Android | iOS |
遇到了问题?
如果您的应用出现了差错,则可使用以下链接中的代码查看最终应用的代码。
8. 做得好!
通过执行下列操作,您编写了一个可在 iOS 和 Android 上运行的交互式 Flutter 应用:
- 编写 Dart 代码
- 使用热重载缩短开发周期
- 使用有状态微件,并向应用中添加交互性
- 创建路由并添加在主路由与新路由之间移动的逻辑
- 了解如何使用主题背景更改应用界面的外观
9. 后续步骤
通过下列资源详细了解 Flutter SDK:
- Flutter 中的布局
- 向您的 Flutter 应用中添加交互性
- 微件简介
- 面向 Android 开发者的 Flutter
- 面向 React Native 开发者的 Flutter
- 面向网页开发者的 Flutter
其他资源包括:
此外,您还可 联系 Flutter 社区!