Flutter是一款移動(dòng)應(yīng)用程序SDK颊糜,一份代碼可以同時(shí)生成iOS和Android兩個(gè)高性能哩治、高保真的應(yīng)用程序,媲美原生應(yīng)用的性能衬鱼,是Google新操作系統(tǒng)Fuchsia的默認(rèn)開發(fā)套件锚扎。
一、 配置環(huán)境
- Android Studio 下載插件Dart馁启、Flutter
- 下載Flutter SDK,配置環(huán)境
二、 第一個(gè)Flutter項(xiàng)目
- File ->new->new Flutter Project
- 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',
//Scaffold包含appBar惯疙、title翠勉、body相當(dāng)于一個(gè)activity
home: new Scaffold(
appBar: new AppBar(
title: new Text('Welcome to Flutter'),
),
//內(nèi)容
body: new Center(
child: new Text('Hello World'),
),
),
);
}
}
運(yùn)行后時(shí)hello world
- 使用外部包(package)
pubspec.yaml是flutter的配置文件,用于管理包和配置flutter信息(等同于build.gradle)霉颠。
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
//添加english_words依賴对碌,指定版本號(hào)
english_words: ^3.1.0
單擊右上角的 Packages get,這會(huì)將依賴包安裝到您的項(xiàng)目
下面就可以在main.dart中使用english_words了
import 'package:english_words/english_words.dart';
final wordPair = new WordPair.random();
// build時(shí)隨機(jī)生成單詞
child: new Text(wordPair.asPascalCase),
點(diǎn)擊熱重載按鍵更新正在運(yùn)行的應(yīng)用程序
二蒿偎、Flutter的交互
1朽们、添加有狀態(tài)的Widget
上面的StatelessWidget是不可變的, 它們的屬性值都是final的
對(duì)應(yīng)的Statefulwidgets則是可變的,它們的屬性值在widget生命周期中都是可以改變的诉位。
實(shí)現(xiàn)一個(gè) stateful widget 至少需要兩個(gè)類:
- 一個(gè) StatefulWidget類骑脱。
- 一個(gè) State類。 StatefulWidget類本身是不變的苍糠,但是 State類在widget生命周期中始終存在.
class RandomWords extends StatefulWidget {
//創(chuàng)建狀態(tài)
@override
createState() => new RandomWordsState();
}
//狀態(tài)類
class RandomWordsState extends State<RandomWords> {
}
2叁丧、創(chuàng)建一個(gè)無限滾動(dòng)ListView
class RandomWordsState extends State<RandomWords> {
//變量以下劃線(_)開頭,在Dart語言中使用下劃線前綴標(biāo)識(shí)符岳瞭,會(huì)強(qiáng)制其變成私有的
final _suggestions = <WordPair>[];
//集合存儲(chǔ)用戶喜歡(收藏)的單詞對(duì)
final _saved = new Set<WordPair>();
final _biggerFont = const TextStyle(fontSize: 18.0);
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Startup Name Generator'),
),
body: _buildSuggestions(),
);
}
Widget _buildSuggestions() {
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
// 對(duì)于每個(gè)建議的單詞對(duì)都會(huì)調(diào)用一次itemBuilder拥娄,然后將單詞對(duì)添加到ListTile行中
// 在偶數(shù)行,該函數(shù)會(huì)為單詞對(duì)添加一個(gè)ListTile row.
// 在奇數(shù)行瞳筏,該行書湖添加一個(gè)分割線widget稚瘾,來分隔相鄰的詞對(duì)。
// 注意姚炕,在小屏幕上摊欠,分割線看起來可能比較吃力。
itemBuilder: (context, i) {
// 在每一列之前钻心,添加一個(gè)1像素高的分隔線widget
if (i.isOdd) return new Divider();
// 語法 "i ~/ 2" 表示i除以2凄硼,但返回值是整形(向下取整),比如i為:1, 2, 3, 4, 5
// 時(shí)捷沸,結(jié)果為0, 1, 1, 2, 2摊沉, 這可以計(jì)算出ListView中減去分隔線后的實(shí)際單詞對(duì)數(shù)量
final index = i ~/ 2;
// 如果是建議列表中最后一個(gè)單詞對(duì)
if (index >= _suggestions.length) {
// ...接著再生成10個(gè)單詞對(duì),然后添加到建議列表
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
});
}
Widget _buildRow(WordPair pair) {
//檢查確保單詞對(duì)還沒有添加到收藏夾
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
//尾部添加icon
trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
//添加交互痒给,輕點(diǎn)監(jiān)聽
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
3说墨、創(chuàng)建可點(diǎn)擊的的List
(1)添加保持狀態(tài)集合
class RandomWordsState extends State<RandomWords> {
//添加保持狀態(tài)集合
final _saved = new Set<WordPair>();
...
}
(2)ListTile中的trailing設(shè)置尾部icon,onTap設(shè)置點(diǎn)擊事件監(jiān)聽
Widget _buildRow(WordPair pair) {
//檢查確保單詞對(duì)還沒有添加到收藏夾
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
//后面添加icon
trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
//添加交互苍柏,輕點(diǎn)監(jiān)聽
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
通過上面的例子尼斧,我們懂得如何Widget去創(chuàng)建的我們的頁(yè)面,保持widget的狀態(tài)试吁,并實(shí)現(xiàn)對(duì)應(yīng)交互棺棵,接下來我們學(xué)習(xí)如何在不同的頁(yè)面間跳轉(zhuǎn)
三楼咳、導(dǎo)航到新的頁(yè)面
1、Flutter中頁(yè)面叫做頁(yè)面路由烛恤,分為主路由和新路由
Navigator通過路由棧來管理各個(gè)路由頁(yè)面母怜,Navigator push一個(gè)路由頁(yè)面時(shí),App會(huì)顯示這個(gè)路由頁(yè)面缚柏,Navigator pop時(shí)苹熏,App將顯示上一個(gè)頁(yè)面。
下面代碼為push一個(gè)頁(yè)面的操作币喧。
void _pushSaved() {
Navigator.of(context).push(
//創(chuàng)建一個(gè)新的頁(yè)面
new MaterialPageRoute(
//構(gòu)建頁(yè)面內(nèi)容
builder: (context) {
//創(chuàng)建list
final tiles = _saved.map(
(pair) {
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
);
},
);
final divided = ListTile
.divideTiles(
context: context,
tiles: tiles,
)
.toList();
// 創(chuàng)建頁(yè)面內(nèi)容:一個(gè)包含喜歡集合的listView
return new Scaffold(
appBar: new AppBar(
title: new Text('Saved Suggestions'),
),
body: new ListView(children: divided),
);
},
),
);
}
四轨域、Flutter Widget概述
Flutter有兩種Widget
五、與React Native對(duì)比
1怜浅、React Native使用HTML+JavaScript渲染成原生控件
優(yōu)點(diǎn):可以完全繼承現(xiàn)代Web開發(fā)的所有成果
缺點(diǎn):將渲染工作交交給系統(tǒng)铐然,雖然同樣使用類HTML+JS的UI構(gòu)建邏輯,但是最終會(huì)生成對(duì)應(yīng)的自定義原生控件恶座,導(dǎo)致框架本身需要處理大量平臺(tái)相關(guān)的邏輯搀暑,隨著系統(tǒng)版本變化和API的變化,開發(fā)者可能也需要處理不同平臺(tái)的差異跨琳。
2自点、Flutter有什么優(yōu)勢(shì)胧瓜?
提高開發(fā)效率
同一份代碼開發(fā)iOS和Android
用更少的代碼做更多的事情
輕松迭代
??在應(yīng)用程序運(yùn)行時(shí)更改代碼并重新加載(通過熱重載疚漆,不需要重啟APP,很快)
??修復(fù)崩潰并繼續(xù)從應(yīng)用程序停止的地方進(jìn)行調(diào)試創(chuàng)建美觀筷弦,高度定制的用戶體驗(yàn)
受益于使用Flutter框架提供的豐富的Material Design和Cupertino(iOS風(fēng)格)的widget
實(shí)現(xiàn)定制溅潜、美觀术唬、品牌驅(qū)動(dòng)的設(shè)計(jì),而不受原生控件的限制
Flutter則開辟了一種全新的思路滚澜,從頭到尾重寫一套跨平臺(tái)的UI框架粗仓,包括UI控件、渲染邏輯甚至開發(fā)語言设捐。渲染引擎依靠跨平臺(tái)的Skia圖形庫(kù)來實(shí)現(xiàn)借浊,依賴系統(tǒng)的只有圖形繪制相關(guān)的接口,可以在最大程度上保證不同平臺(tái)萝招、不同設(shè)備的體驗(yàn)一致性蚂斤,邏輯處理使用支持AOT的Dart語言,執(zhí)行效率也比JavaScript高得多槐沼。
六曙蒸、Flutter學(xué)習(xí)資料
Flutter中文網(wǎng)站
https://flutterchina.club/get-started/install/
Flutter GitHub
https://github.com/flutter/flutter
Flutter examples
https://github.com/flutter/flutter/tree/master/examples