Flutter初体验(二)—— 创建第一个Flutter APP
Flutter初体验(二)— 创建第一个Flutter APP 在第一篇文章 Flutter初体验(一)—Mac 安装配置,学习了配置 Flutter 开发环境,并运行了Demo项目,本篇根据官方教程,学习创建自己的第一个Flutter APP。 参考文档 https://flutter.io/get-started/codelab/ 项目需求您将实施一个简单的移动应用程序,为一家创业公司生成建议名称。用户可以选择和取消选择名称,保存最好的名称。该代码一次生成十个名称。当用户滚动时,会生成新批次的名称。用户可以点击应用栏右上方的列表图标以移动到仅列出收藏名称的新路线
学习成果:
第1步 :创建一个运行的Flutter 应用程序在第一篇文章中已经讲述了如何配置Flutter开发环境,并且创建一个示例Flutter项目,现在将会修改这个示例程序来完成我们的项目。 本次操作,主要编辑Dart代码中的lib/main.dart。
1.替换 lib/main.dart. import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Welcome to Flutter',home: new Scaffold(
appBar: new AppBar(
title: new Text('Welcome to Flutter'),),body: new Center(
child: new Text('Hello World'),);
}
}
2.运行工程,将会看到下面的屏幕截图 总结
第2步:使用外部包在这一步中,您将开始使用名为english_words的开源软件包,其中包含数千个最常用的英文单词以及一些实用功能 dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.0 english_words: ^3.1.0
2.在Android Studio的编辑器视图,单击右上角Packages get。将该包引入您的项目。将会在控制台中看到以下内容 flutter packages get
Running "flutter packages get" in flutter_app...
Process finished with exit code 0
3.在lib / main.dart中,将english_words导入,如下所示: import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
在输入过程中,Android Studio会为您提供有关库导入的建议。然后它将呈现灰色的导入字符串,让您知道导入的库未使用(到目前为止) 4.使用English words 包来生成文本取代字符串“Hello World” import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final wordPair = new WordPair.random();
return new MaterialApp(
title: 'Welcome to Flutter',home: new Scaffold(
appBar: new AppBar(
title: new Text('Welcome to Flutter'),body: new Center(
//child: new Text('Hello World'),// Replace the highlighted text...
child: new Text(wordPair.asPascalCase),// With this highlighted text.
),);
}
}
5.如果应用程序正在运行,使用热重载按钮(??)更新正在运行的应用程序,每次点击热重载或者保存项目时,都会在正在运行的应用程序中随机显示一个不同的单词,这是单词配对是在构建方法内部生成的,每次MaterialApp需要渲染时都会运行它,或在检查器中切换平台时。 第3步:添加一个有状态的组件无状态组件是不可变的,意味着他们的属性不能被改变–所有的值都是最终值 有状态的小部件保持在小部件的生命周期中可能改变的状态,实现一个有状态的小部件至少需要两个类:1)一个StatefulWidget类,它创建一个取代 2)一个State类的实例。 StatefulWidget类本身是不可变的,但State类在整个构件的生命周期中保持不变 在这一步中,您将添加一个有状态的小部件RandomWords,它创建其状态类RandomWordsState class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
2.添加RandomWordsState类。该应用程序的大部分代码都驻留在该类中,该类保持RandomWords小部件的状态,这个类将保存随着用户滚动而无限增长的生成的单词对,以及最喜欢的单词对,因为用户通过切换红心图标来将它们从列表中添加或删除。 你会一点一点地建立这个类。首先,通过添加突出显示的文本创建一个最小类: class RandomWordsState extends State<RandomWords> {
}
3.在添加状态类后,IDE会抱怨该类缺少构建方法,接下来,您将添加一个基本构建方法,该方法通过将单词生成代码从MyApp移动到RandomWordsState来生成单词对 将构建方法添加到RandomWordState中,如突出显示的文本所示: class RandomWordsState extends State<RandomWords> {
@override
Widget build(BuildContext context) {
final wordPair = new WordPair.random();
return new Text(wordPair.asPascalCase);
}
}
4.通过下面突出显示的更改从MyApp中删除单词生成代码: class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Welcome to Flutter',body: new Center(
//child: new Text(wordPair.asPascalCase),// Change the highlighted text to...
child: new RandomWords(),// ... this highlighted text
),);
}
}
重新启动应用程序。如果您尝试重新加载热点,则可能会看到警告: Reloading...
Not all changed program elements ran during view reassembly; consider
restarting.
这可能是误报,但考虑重新启动以确保您的更改反映在应用的用户界面中。 应用程序应该像以前一样运行,每次热重新加载或保存应用程序时都会显示一个字对。 第4步:创建一个无限的滚动ListView在这一步中,您将展开RandomWordsState以生成并显示单词配对列表。当用户滚动时,ListView小部件中显示的列表将无限增长。 ListView的构建器工厂构造函数允许您根据需要懒惰地构建列表视图。 1.将一个 另外,添加一个largerFont变量来使字体变大。 class RandomWordsState extends State<RandomWords> {
...
final _suggestions = <WordPair>[];
final _biggerFont = const TextStyle(fontSize: 18.0);
}
2.将一个 ListView类提供了一个构建器属性itemBuilder,一个指定为匿名函数的工厂构建器和回调函数,两个参数传递给函数 - BuildContext和行迭代器.迭代器从0开始,每次调用该函数时递增,每次建议的单词配对一次.该模型允许建议的列表在用户滚动时无限增长。 class RandomWordsState extends State<RandomWords> {
...
Widget _buildSuggestions() {
return new ListView.builder(
padding: const EdgeInsets.all(16.0),// The itemBuilder callback is called once per suggested word pairing,
// and places each suggestion into a ListTile row.
// For even rows,the function adds a ListTile row for the word pairing.
// For odd rows,the function adds a Divider widget to visually
// separate the entries. Note that the divider may be difficult
// to see on smaller devices.
itemBuilder: (context,i) {
// Add a one-pixel-high divider widget before each row in theListView.
if (i.isOdd) return new Divider();
// The syntax "i ~/ 2" divides i by 2 and returns an integer result.
// For example: 1,2,3,4,5 becomes 0,1,2.
// This calculates the actual number of word pairings in the ListView,
// minus the divider widgets.
final index = i ~/ 2;
// If you've reached the end of the available word pairings...
if (index >= _suggestions.length) {
// ...then generate 10 more and add them to the suggestions list.
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
}
);
}
}
3. 向 class RandomWordsState extends State<RandomWords> {
...
Widget _buildRow(WordPair pair) {
return new ListTile(
title: new Text(
pair.asPascalCase,style: _biggerFont,);
}
}
4.更新RandomWordsState的构建方法以使用 class RandomWordsState extends State<RandomWords> {
...
@override
Widget build(BuildContext context) {
//final wordPair = new WordPair.random(); // Delete these two lines.
//return new Text(wordPair.asPascalCase);
return new Scaffold (
appBar: new AppBar(
title: new Text('Startup Name Generator'),body: _buildSuggestions(),);
}
...
}
5.更新MyApp的构建方法。从MyApp中删除Scaffold和AppBar实例。这些将由RandomWordsState管理,当用户在下一步中从一个屏幕导航到另一个屏幕时,可以更轻松地更改应用栏中的路由名称。 用下面突出显示的构建方法替换原始方法: class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Startup Name Generator',home: new RandomWords(),);
}
}
重新启动应用程序。你应该看到一个单词配对清单。尽可能向下滚动,您将继续看到新的单词配对。 第5步:添加交互性在这一步中,您将为每一行添加可点击的心形图标。当用户点击列表中的条目,切换其“收藏”状态时,该单词配对被添加到一组保存的收藏夹中或从中删除 1.将一个 class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _saved = new Set<WordPair>(); //添加 saved 集合
final _biggerFont = const TextStyle(fontSize: 18.0);
}
2.在 Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
...
}
3.同样在_buildRow()中,将心形图标添加到ListTiles以启用收藏。稍后,您将添加与心形图标进行交互的功能。 添加下面突出显示的行: Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,//添加心形图标以添加收藏功能
trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,color: alreadySaved ? Colors.red : null,);
}
4.重新启动应用程序。你现在应该在每一行看到开放的心,但它们还没有互动。 5.在 添加下列代码: Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,//修改心形图标的状态
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},);
}
热重载应用程序。你应该能够点击任何一行以获得最喜欢的,或不适合的条目。注意,点击一行会生成从心形图标散发的涟漪动画。 第6步:导航到新的屏幕在这一步中,您将添加一个显示收藏夹的新屏幕(在Flutter中称为路线)。您将学习如何在主路线和新路线之间导航。 在Flutter中,导航器管理包含应用程序路线的堆栈。将路线推入导航器的堆栈,将显示更新为该推入的路线。从导航器的堆栈中弹出路径,将显示返回到上一个路线。 1.向RandomWordsState的构建方法中的AppBar添加列表图标。当用户点击列表图标时,包含收藏夹项目的新路线被推送到导航器,显示该图标。
class RandomWordsState extends State<RandomWords> {
...
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Startup Name Generator'),//添加actions
actions: <Widget>[
new IconButton(icon: new Icon(Icons.list),onPressed: _pushSaved),],);
}
...
}
2.将一个 class RandomWordsState extends State<RandomWords> {
...
void _pushSaved() {
}
}
热重新加载应用程序。列表图标出现在应用程序栏中。点击它什么也没做,因为 3.当用户点击应用栏中的列表图标时,建立一条路线并将其推送到导航器的堆栈。此操作会更改屏幕以显示新路线。 新页面的内容是使用匿名函数在MaterialPageRoute的构建器属性中构建的。 将呼叫添加到Navigator.push,如突出显示的代码所示,将路线推送到导航器的堆栈。 void _pushSaved() {
Navigator.of(context).push(
);
}
4.添加MaterialPageRoute及其构建器。现在,添加生成ListTile行的代码。ListTile void _pushSaved() {
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) {
final tiles = _saved.map(
(pair) {
return new ListTile(
title: new Text(
pair.asPascalCase,);
},);
final divided = ListTile
.divideTiles(
context: context,tiles: tiles,)
.toList();
},);
}
5.构建器属性返回一个Scaffold,其中包含名为“Saved Suggestions”的新路线的应用程序栏。新路由的主体由包含ListTiles行的ListView组成;每行由一个分隔符分隔。 添加下面突出显示的代码: void _pushSaved() {
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) {
final tiles = _saved.map(
(pair) {
return new ListTile(
title: new Text(
pair.asPascalCase,)
.toList();
//添加 Scaffold 名为 Saved Suggestions
return new Scaffold(
appBar: new AppBar(
title: new Text('Saved Suggestions'),body: new ListView(children: divided),);
},);
}
6.热重载应用程序。最喜欢的一些选择,并点击应用栏中的列表图标。新路线显示包含收藏夹。请注意,导航器会在应用栏中添加一个“返回”按钮。你不必显式实现Navigator.pop。点击后退按钮返回到主页路线。 第7步:使用主题更改UI在最后一步中,您将使用该应用的主题,主题控制你的应用的外观和感觉。您可以使用默认主题,该主题取决于物理设备或模拟器,也可以自定义主题以反映您的品牌。 1.您可以通过配置ThemeData类轻松更改应用程序的主题。您的应用程序目前使用默认主题,但您将更改主要颜色为白色。 将突出显示的代码添加到MyApp,将应用程序的主题更改为蓝色: class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Startup Name Generator',//修改主题颜色
theme: new ThemeData(
primaryColor: Colors.blue,);
}
}
2.热重新加载应用程序。请注意,整个背景是白色的,甚至是应用栏。 3.作为读者的练习,使用ThemeData来改变用户界面的其他方面。材质库中的Colors类提供了许多可以使用的颜色常量,而热重载使得用户界面的试验变得快速而简单。 搞定!我们编写了一个在iOS和Android上运行的交互式Flutter应用程序。在这个codelab中,你有:
第一篇文章: Flutter初体验(一)—Mac 安装配置 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |