1. 編寫(xiě) Flutter 程序
下文是按照官方文檔隨便體驗(yàn)一下,有興趣直接開(kāi)始Flutter編程的可以點(diǎn)這里。
2. 創(chuàng)建 flutter App
創(chuàng)建一個(gè)flutter App,可以參考創(chuàng)建流程
3. 運(yùn)行 App
flutter run
4. 編輯第一個(gè) Hello world程序
刪除 main.dart 文件內(nèi)容,復(fù)制粘貼以下代碼,保存后刷新模擬器,可以參考flutter基本操作
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'),
),
),
);
}
}
5. 使用 Package
導(dǎo)入english_words的開(kāi)源軟件包 ,其中包含數(shù)千個(gè)最常用的英文單詞以及一些實(shí)用功能.
首先打開(kāi)App目錄下 pubspec.yaml 文件,在 dependencies 下新增 english_words
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.0
english_words: ^3.1.0
保存后,運(yùn)行以下命令安裝
flutter pub get
安裝完成后,重新啟動(dòng)模擬器
flutter run
在 main.dart 文件中導(dǎo)入頭文件,并修改部分代碼,如下
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final wordPair = new WordPair.random();
return new MaterialApp (
title : 'Welcome',
home : new Scaffold(
appBar: new AppBar( title: new Text('Welcome to Flutter') ),
body : new Center(child: new Text(wordPair.asPascalCase)),
),
);
}
}
保存后,刷新模擬器

simulator.png
6. 添加一個(gè) Stateful widget (標(biāo)記狀態(tài)的組件)
復(fù)制粘貼以下代碼至 main.dart ,具體組件功能后續(xù)文章再做講解。
運(yùn)行后與之前效果完全相同,只不過(guò)是將 Text(wordPair.asPascalCase) 生成的隨機(jī)單詞換成 RandomWords() 生成的隨機(jī)單詞。
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp (
title : 'Welcome',
home : new Scaffold(
appBar: new AppBar( title: new Text('Welcome to Flutter') ),
body : new Center(child: new RandomWords()),
),
);
}
}
class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
class RandomWordsState extends State <RandomWords> {
@override
Widget build(BuildContext context) {
final wordPair = new WordPair.random();
return new Text(wordPair.asPascalCase);
}
}
7. 創(chuàng)建一個(gè) ListView (TableView)
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp (
title : 'Welcome',
home : new RandomWords(),
);
}
}
class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
class RandomWordsState extends State <RandomWords> {
@override
final _suggestions = <WordPair>[];
final _biggerFont = const TextStyle(fontSize : 18.0);
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('ListView')),
body: _buildSuggestions(),
);
}
Widget _buildSuggestions() {
return new ListView.builder(
padding : const EdgeInsets.all(16.0),
itemBuilder : (context, i){
if (i.isOdd) return new Divider();
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
}
);
}
Widget _buildRow(WordPair pair) {
return new ListTile(
title : new Text(
pair.asPascalCase,
style: _biggerFont,
)
);
}
}
運(yùn)行后如下

simulator_listview.png
8. 添加 ListView 的點(diǎn)擊事件,并對(duì)點(diǎn)擊狀態(tài)進(jìn)行保存
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp (
title : 'Welcome',
home : new RandomWords(),
);
}
}
class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
class RandomWordsState extends State <RandomWords> {
@override
final _suggestions = <WordPair>[];
final _saved = new Set<WordPair>();
final _biggerFont = const TextStyle(fontSize : 18.0);
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('ListView')),
body: _buildSuggestions(),
);
}
Widget _buildSuggestions() {
return new ListView.builder(
padding : const EdgeInsets.all(16.0),
itemBuilder : (context, i){
if (i.isOdd) return new Divider();
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
}
);
}
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return new ListTile(
title : new Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: (){
setState((){
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
}
運(yùn)行刷新后如下

simulator_state.png
9. 通過(guò)路由實(shí)現(xiàn) flutter 的頁(yè)面跳轉(zhuǎn)
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp (
title : 'Welcome',
home : new RandomWords(),
);
}
}
class RandomWords extends StatefulWidget {
@override
createState() => new RandomWordsState();
}
class RandomWordsState extends State <RandomWords> {
@override
final _suggestions = <WordPair>[];
final _saved = new Set<WordPair>();
final _biggerFont = const TextStyle(fontSize : 18.0);
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('ListView'),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved),
],
),
body: _buildSuggestions(),
);
}
Widget _buildSuggestions() {
return new ListView.builder(
padding : const EdgeInsets.all(16.0),
itemBuilder : (context, i){
if (i.isOdd) return new Divider();
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
}
);
}
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return new ListTile(
title : new Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: (){
setState((){
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
void _pushSaved(){
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) {
final tiles = _saved.map(
(pair) {
return new ListTile (
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
);
},
);
final divided = ListTile.divideTiles(
context: context,
tiles: tiles,
)
.toList();
return new Scaffold(
appBar: new AppBar(
title: new Text('Saved Suggestions'),
),
body: new ListView(children: divided),
);
},
),
);
}
}
保存運(yùn)行后如圖

simulator_route_home.png

simulator_route_push.png
10. 更改主題色
通過(guò) ThemeData 類來(lái)改變主題色,修改以下部分代碼
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp (
title : 'Welcome',
theme: new ThemeData(
primaryColor: Colors.white,
),
home : new RandomWords(),
);
}
}
保存運(yùn)行后如下圖

simulator_route_home_white.png

simulator_route_push_white.png
11. 小結(jié)
本文到這里就結(jié)束了,全部代碼均為跟著官方教程走了一遍。主要就以下幾個(gè)功能點(diǎn)
- ListView 的創(chuàng)建
- ListView 的Item狀態(tài)及保存
- Item 的狀態(tài)保存及按照不同的狀態(tài)刷新UI
- Route 的頁(yè)面跳轉(zhuǎn)及回跳
- 主題色的修改