Flutter框架概覽
Flutter是什么
- 是一款移動(dòng)應(yīng)用程序SDK吊圾,一份代碼可以同時(shí)生成ios和Android兩個(gè)高性能闷愤、高保真的應(yīng)用程序
- 目標(biāo)是使開(kāi)發(fā)人員能夠交付在不同平臺(tái)上都感覺(jué)自然流暢的高性能應(yīng)用程序。我們兼容滾動(dòng)行為丙猬,排版,圖標(biāo)等方面的差異
Flutter優(yōu)勢(shì)
- 跨平臺(tái):至少可以跨4種平臺(tái),甚至支持嵌入式開(kāi)發(fā)肿轨,常用的有(Linux,Android蕊程,IOS椒袍,甚至可以在谷歌最新的操作系統(tǒng)上Fuchsia進(jìn)行運(yùn)行),經(jīng)過(guò)第三方擴(kuò)展藻茂,甚至可以跑在MacOS和Windows上驹暑。Flutter算是支持平臺(tái)最多的框架,良好的跨平臺(tái)性辨赐,減少開(kāi)發(fā)成本
- 原生用戶界面:它是原生的优俘,體驗(yàn)好,性能好
- 開(kāi)源免費(fèi)
主流框架的對(duì)比
- Cordova:Cordova基于網(wǎng)頁(yè)技術(shù)進(jìn)行包裝掀序,利用插件的形式開(kāi)發(fā)移動(dòng)應(yīng)用
- RN(React Native):RN的效率由于是將View編譯成了原生View帆焕,所以效率上要比基于Cordova的HTML5高很多,但是它也有效率問(wèn)題不恭,RN的渲染機(jī)制是基于前端框架的考慮叶雹,復(fù)雜的UI渲染是需要依賴多個(gè)view疊加,RN的列表方案不友好
- Flutter:在渲染技術(shù)上换吧,選擇了自己實(shí)現(xiàn)(GDI)折晦,有更好的可控性,使用了新的語(yǔ)言Dart沾瓦,避免了RN的那種通過(guò)橋接器與Javascript通訊導(dǎo)致效率底下的問(wèn)題满着,所以性能方面比RN更高一籌;
120fps超高性能
Flutter采用GPU渲染技術(shù)暴拄,所以性能極高
Flutter編寫的應(yīng)用是可以達(dá)到120fps(每秒傳輸幀數(shù)),完全可以勝任游戲的制作漓滔,RN的性能只能達(dá)到60fps。
核心原則
Flutter包括一個(gè)現(xiàn)代的響應(yīng)式框架乖篷,一個(gè)2D渲染引擎响驴,現(xiàn)成的widget和開(kāi)發(fā)工具
Dart語(yǔ)法Function函數(shù)
Dart是面向?qū)ο蟮恼Z(yǔ)言,即使是函數(shù)也是對(duì)象撕蔼,并且屬于Function類型的對(duì)象豁鲤,這意味著函數(shù)可以分配給變量或作為參數(shù)傳遞給其他函數(shù)
Dart是一切皆對(duì)象秽誊,包括數(shù)字和函數(shù)
StatefulWidget和StatelessWidget
- StatefulWidget:具有可變狀態(tài)的窗口部件,也就是你在使用應(yīng)用的時(shí)候就可以隨時(shí)變化琳骡,如果常見(jiàn)的進(jìn)度條锅论,隨著進(jìn)度不斷變化
- StatelessWidge:不可變狀態(tài)窗口部件,也就是你在使用時(shí)不可以改變楣号,如果固定的文字
flutter的基本代碼
import 'package:flutter/material.dart';
//主函數(shù)(入口函數(shù))最易,下面我會(huì)簡(jiǎn)單說(shuō)說(shuō)Dart的函數(shù)
void main() =>runApp(MyApp());
// 聲明MyApp類
class MyApp extends StatelessWidget{
//重寫build方法
@override
Widget build(BuildContext context){
//返回一個(gè)Material風(fēng)格的組件
return MaterialApp(
title:'Welcome to Flutteraa',
home:Scaffold(
//創(chuàng)建一個(gè)Bar,并添加文本
appBar:AppBar(
title:Text('Welcome to Flutter'),
),
//在主體的中間區(qū)域炫狱,添加一個(gè)hello world 的文本
body:Center(
child:Text(
'Hello JSPang ,非常喜歡前端藻懒,并且愿意為此奮斗一生。我希望可以出1000集免費(fèi)教程视译。',
textAlign:TextAlign.left,
overflow:TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontSize:25.0,
color:Color.fromARGB(255, 255, 150, 150),
decoration:TextDecoration.underline,
decorationStyle:TextDecorationStyle.solid,
),
),
),
),
);
}
}
常用組件
Container容器組件的使用
Alignment屬性:這個(gè)屬性針對(duì)的是Container內(nèi)child的對(duì)齊方式嬉荆,也就是容器子內(nèi)容的對(duì)齊方式,并不是容器本身的對(duì)齊方式
child:Container(
child:new Text('Hello JSPang',style: TextStyle(fontSize: 40.0),),
alignment: Alignment.center,
),
- bottomCenter:下部居中對(duì)齊
- bottomLeft:下部左對(duì)齊
- bottomRight:下部右對(duì)齊
- center:縱橫雙向居中對(duì)齊
- centerLeft:縱向居中橫向居左對(duì)齊
- centerRight:縱向居中橫向居右對(duì)齊
- topLeft:頂部左側(cè)對(duì)齊
- topCenter:頂部居中對(duì)齊
- topRight:頂部居左對(duì)齊
設(shè)置寬酷含,高和顏色屬性
設(shè)置寬鄙早,高和顏色屬性只要在屬性名稱后加入浮點(diǎn)型數(shù)字就可以
child:Container(
child:new Text('Hello JSPang',style: TextStyle(fontSize: 40.0),),
alignment: Alignment.center,
width:500.0,
height:400.0,
color: Colors.lightBlue,
),
padding,margin椅亚,decoration
padding
padding:const EdgeInsets.all(10.0),
padding:const EdgeInsets.fromLTRB(value1,value2,value3,value4)
// 我們用EdgeInsets.fromLTRB(value1,value2,value3,value4) 可以滿足我們的需求限番,LTRB分別代表左、上什往、右扳缕、下。
margin
// margin是container和外部元素的距離
margin: const EdgeInsets.all(10.0),
margin:const EdgeInsets.fromLTRB(value1,value2,value3,value4)
decoration
// decoration是container的修飾器别威,主要的功能是設(shè)置背景和邊框
// 如果要給背景加入一個(gè)漸變躯舔,需要使用BoxDecoration這個(gè)類,(注意省古,如果設(shè)置了decoration粥庄,就不要再設(shè)置color屬性了,會(huì)沖突)
decoration: BoxDecoration(
gradient: const LinearGradient(colors: [Colors.lightBlue,Colors.greenAccent,Colors.purple] )),
border
border:Border.all(width:2.0,color:Colors.red)
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter 學(xué)習(xí)',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Iris'),
),
body: Center(
child: Container(
child: new Text('世界那么大豺妓,我想去看看',style: TextStyle(fontSize: 20.0),),
alignment: Alignment.center,
width: 500.0,
height: 400.0,
padding: const EdgeInsets.fromLTRB(10.0, 30.0, 0.0, 0.0),
margin: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.lightBlue,Colors.greenAccent,Colors.purple]
),
border: Border.all(width: 1.0,color: Colors.red)
),
),
),
),
);
}
}
加入圖片的幾種方式
- Image.asset:加載資源圖片惜互,就是加載項(xiàng)目資源目錄中的圖片,加入圖片后會(huì)增大打包的包體體積琳拭,用的是相對(duì)路徑
- Image.network:網(wǎng)絡(luò)資源圖片训堆,意思就是需要加入一段http://xxxx.xxx的這樣的網(wǎng)絡(luò)路徑地址
- Image.file:加載本地圖片,就是加載本地文件中的圖片白嘁,這是一個(gè)絕對(duì)路徑坑鱼,跟包體無(wú)關(guān)
- Image.memory:加載Uint8List資源圖片
fit屬性的設(shè)置
- BoxFit.fill:全圖顯示,圖片會(huì)被拉伸絮缅,并充滿父容器
- BoxFit.contain:全圖顯示鲁沥,顯示原比例呼股,可能會(huì)有空隙
- BoxFix.cover:顯示可能拉伸,可能裁切画恰,充滿(圖片要充滿整個(gè)容器彭谁,還不變形 )
- BoxFit.fitWidth:寬度充滿(橫向充滿),顯示可能拉伸允扇,可能裁切
- BoxFit.fitHeight:高度充滿(豎向充滿),顯示可能拉伸缠局,可能裁切
- BoxFit.scaleDown:效果和contain差不多,但是此屬性不允許顯示超過(guò)源圖片大小蔼两,可小不可大
圖片的混合模式
圖片混合模式(colorBlendMode)和color屬性配合使用甩鳄,能讓圖片改變顏色逞度,里面的模式非常多额划,產(chǎn)生的效果也非常豐富
child:new Image.network(
'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2247692397,1189743173&fm=5',
color: Colors.greenAccent,
colorBlendMode: BlendMode.darken,
),
- color:是要混合的顏色,如果你只設(shè)置color是沒(méi)有意義的
- colorBlendMode:是混合模式
repeat圖片重復(fù)
- ImageRepeat.repeat :橫向和縱向都進(jìn)行重復(fù)档泽,直到鋪滿整個(gè)畫布
- ImageRepeat.repeatX:橫向重復(fù)俊戳,縱向不重復(fù)
- ImageRepeat.repeatY:縱向重復(fù),橫向不重復(fù)
child:new Image.network(
'http://jspang.com/static/myimg/blogtouxiang.jpg',
repeat: ImageRepeat.repeat,
),
body: Center(
child: Container(
child:new Image.network(
'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2247692397,1189743173&fm=5',
scale: 1.0,
// fit: BoxFit.cover,
color: Colors.greenAccent,
colorBlendMode: BlendMode.darken,
repeat: ImageRepeat.repeat,
),
width: 500.0,
height: 600.0,
color: Colors.lightBlue,
),
),
ListView列表組件簡(jiǎn)介
ListTile組件
body: new ListView(
children:<Widget>[
new ListTile(
leading:new Icon(Icons.access_time),
title:new Text('access_time')
),
new ListTile(
leading:new Icon(Icons.account_balance),
title:new Text('account_balance')
),
]
),
圖片列表的使用
body: new ListView(
children: <Widget>[
new Image.network( 'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2247692397,1189743173&fm=5'),
new Image.network( 'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=1569462993,172008204&fm=5'),
new Image.network( 'https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=1853832225,307688784&fm=5')
],
),
橫向列表的使用
body: Center(
child: Container(
height: 200.0,
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
new Container(
width: 180.0,
color: Colors.lightBlue,
),new Container(
width: 180.0,
color: Colors.amber,
),new Container(
width: 180.0,
color: Colors.deepOrange,
),new Container(
width: 180.0,
color: Colors.deepPurpleAccent,
)
],
),
),
)
scrollDirection屬性
ListView組件的scrollDirection屬性只是兩個(gè)值馆匿,一個(gè)是橫向滾動(dòng)抑胎,一個(gè)是縱向滾動(dòng),默認(rèn)的就是垂直滾動(dòng)渐北,所以如果是垂直滾動(dòng)阿逃,一般不進(jìn)行設(shè)置
- Axis.horizontal:橫向滾動(dòng)或者叫水平方向滾動(dòng)
- Axis.vertical:縱向滾動(dòng)或者叫垂直方向滾動(dòng)
代碼優(yōu)化
// 使用類,減少嵌套
import 'package:flutter/material.dart';
void main () => runApp(MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
body:Center(
child:Container(
height:200.0,
child:MyList()
),
),
),
);
}
}
class MyList extends StatelessWidget{
@override
Widget build(BuildContext context){
return ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
new Container(
width:180.0,
color: Colors.lightBlue,
), new Container(
width:180.0,
color: Colors.amber,
), new Container(
width:180.0,
color: Colors.deepOrange,
),new Container(
width:180.0,
color: Colors.deepPurpleAccent,
),
],
);
}
}
List類型的使用
List是Dart的集合類型之一赃蛛,可以理解為數(shù)組恃锉,它聲明的幾種方式
-
var myList = List()
:非固定長(zhǎng)度的聲明 -
var myList = List(2)
:固定長(zhǎng)度的聲明 -
var myList = List<string>()
:固定類型的聲明方式 -
var myList = [1,2,3]
:對(duì)List直接賦值
使用一個(gè)List傳遞,然后直接用List中的generate
方法進(jìn)行生產(chǎn)List里的元素呕臂。最后生產(chǎn)一個(gè)帶值的List變量
void main () => runApp(MyApp(
items: new List<String>.generate(1000, (i)=> "Item $i")
));
// main函數(shù)的runApp中調(diào)用了MyApp類破托,再使用類傳遞了一個(gè)item參數(shù),并使用generate生成器對(duì)item進(jìn)行賦值
// generate方法傳遞兩個(gè)參數(shù)歧蒋,第一個(gè)參數(shù)是生成的個(gè)數(shù)土砂,第二個(gè)是方法
接受參數(shù)
final List<String> items;
MyApp({Key key, @required this.items}):super(key:key)
// 構(gòu)造函數(shù),@required是比傳的意思谜洽,:super如果父類沒(méi)有無(wú)名無(wú)參的默認(rèn)構(gòu)造函數(shù)萝映,子類必須手動(dòng)調(diào)用一個(gè)父類構(gòu)造函數(shù)
動(dòng)態(tài)列表ListView.builder()
import 'package:flutter/material.dart';
void main () => runApp(MyApp(
// 傳遞參數(shù)
items: new List<String>.generate(1000, (i)=> "Item $i")
));
class MyApp extends StatelessWidget{
// 接受參數(shù)
final List<String> items;
MyApp({Key key, @required this.items}):super(key:key);
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',
home:Scaffold(
// 動(dòng)態(tài)列表
body:new ListView.builder(
itemCount:items.length,
itemBuilder:(context,index){
return new ListTile(
title:new Text('${items[index]}'),
);
}
)
),
);
}
}
GridView網(wǎng)格列表組件
網(wǎng)格列表常用來(lái)顯示多張圖片,類似于相冊(cè)功能
body: new GridView.count(
padding: const EdgeInsets.all(20.0),
crossAxisSpacing: 10.0,
crossAxisCount: 3,
children: <Widget>[
const Text('我的呱呱'),
const Text('我喜歡吃'),
const Text('我是個(gè)淑女的小姐姐'),
const Text('我是個(gè)會(huì)寫代碼的萌妹紙'),
const Text('我喜歡吃火鍋'),
const Text('我喜歡看書(shū)')
],
)
// padding 內(nèi)邊距
// crossAxisSpacing: 網(wǎng)格間的空擋阐虚,相當(dāng)于每個(gè)網(wǎng)格間的距離
// crossAxisCount: 網(wǎng)格的列數(shù)序臂,相當(dāng)于一行放置網(wǎng)格的數(shù)量
GridView.count:創(chuàng)建一個(gè)在橫軸上具有固定數(shù)量網(wǎng)格塊的平鋪的布局
GridView.extent:使用具有最大橫軸范圍的網(wǎng)格塊創(chuàng)建布局
自定義SliverGridDelegate:可以生成任意2D排列的子代,包括未對(duì)齊或重疊的排列
-
要?jiǎng)?chuàng)建具有大量(或無(wú)限)個(gè)子節(jié)點(diǎn)的網(wǎng)絡(luò)敌呈,將GridView.builder構(gòu)造函數(shù)與gridDelegate的 SliverGridDelegateWithFixedCrossAxisCount 或SliverGridDelegateWithMaxCrossAxisExtent 一起使用
http://www.reibang.com/p/aec6fee34f70(詳細(xì)信息)
import 'package:flutter/material.dart';
// 主函數(shù)(入口函數(shù))
void main() => runApp(MyApp(
// 傳遞參數(shù)
// items: new List<String>.generate(10, (i)=>"Item $i")
));
// 聲明MyApp類
class MyApp extends StatelessWidget{
// 接受參數(shù)
// final List<String> items;
// MyApp({Key key, @required this.items}):super(key:key);
// 重寫build方法
@override
Widget build(BuildContext context){
// 返回一個(gè)Material風(fēng)格的組件
return MaterialApp(
title: '好好學(xué)習(xí)',
home: Scaffold(
// 主體中間區(qū)域
body: new GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 2.0,
crossAxisSpacing: 2.0,
childAspectRatio: 0.7
),
children: <Widget>[
new Image.network('http://img5.mtime.cn/mt/2018/10/22/104316.77318635_180X260X4.jpg',fit:BoxFit.cover),
new Image.network('http://img5.mtime.cn/mt/2018/10/10/112514.30587089_180X260X4.jpg',fit:BoxFit.cover),
new Image.network('http://img5.mtime.cn/mt/2018/11/13/093605.61422332_180X260X4.jpg',fit:BoxFit.cover),
new Image.network('http://img5.mtime.cn/mt/2018/11/07/092515.55805319_180X260X4.jpg',fit:BoxFit.cover),
new Image.network('http://img5.mtime.cn/mt/2018/11/21/090246.16772408_135X190X4.jpg',fit:BoxFit.cover),
new Image.network('http://img5.mtime.cn/mt/2018/11/17/162028.94879602_135X190X4.jpg',fit:BoxFit.cover),
new Image.network('http://img5.mtime.cn/mt/2018/11/19/165350.52237320_135X190X4.jpg',fit:BoxFit.cover),
new Image.network('http://img5.mtime.cn/mt/2018/11/16/115256.24365160_180X260X4.jpg',fit:BoxFit.cover),
new Image.network('http://img5.mtime.cn/mt/2018/11/20/141608.71613590_135X190X4.jpg',fit:BoxFit.cover),
],
)
),
);
}
}
// childAspectRatio:寬高比
布局
第01節(jié)水平布局Row的使用
Flutter中的row控件是水平控件贸宏,可以讓Row子元素進(jìn)行水平排列
Row控件可以分為靈活排列和非靈活排列兩種
不靈活水平布局:根據(jù)Row子元素的大小造寝,進(jìn)行布局,如果子元素不足吭练,會(huì)留有空間诫龙,如果子元素超出,會(huì)警告
//按鈕
new RaisedButton(
onPressed: (){
},
color:Colors.orangeAccent,
child: new Text('黃色按鈕'),
),
靈活布局:使用Expanded來(lái)解決空隙問(wèn)題鲫咽,在按鈕外邊加入Expanded就可以了
Expanded(
child: new RaisedButton(
onPressed: (){},
color: Colors.pinkAccent,
child: new Text('粉色按鈕'),
)
)
注意:還可以靈活和不靈活混合使用
第02節(jié):垂直布局Column組件
Column組件就是垂直布局控件签赃,能夠?qū)⒆咏M件垂直排列
body:Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('I am JSPang'),
Text('my website is jspang.com'),
Text('I love coding')
],
)
// CrossAxisAlignment.star:居左對(duì)齊。
// CrossAxisAlignment.end:居右對(duì)齊分尸。
// CrossAxisAlignment.center:居中對(duì)齊锦聊。
主軸和副軸
mainAxisAlignment 主軸對(duì)齊方式
- main軸:主軸(根據(jù)組件判斷主軸,column組件箩绍,和Row組件)
- cross軸:副軸
第03節(jié):Stack層疊布局
// 聲明MyApp類
class MyApp extends StatelessWidget{
// 接受參數(shù)
// final List<String> items;
// MyApp({Key key, @required this.items}):super(key:key);
// 重寫build方法
@override
Widget build(BuildContext context){
// 返回一個(gè)Material風(fēng)格的組件
var stack = new Stack(
alignment: const FractionalOffset(0.5, 0.95),
children: <Widget>[
new CircleAvatar(
backgroundImage: new NetworkImage('https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2247692397,1189743173&fm=5'),
radius: 100.0,
),
new Container(
decoration: new BoxDecoration(
color: Colors.lightGreen
),
padding: EdgeInsets.fromLTRB(20.0,3.0,20.0,3.0),
child: Text('布偶',style: TextStyle(fontSize: 18.0,color: Colors.blueGrey),),
)
],
);
return MaterialApp(
title: '好好學(xué)習(xí)',
home: Scaffold(
appBar: new AppBar(
title: new Text('水平方向布局'),
),
// 主體中間區(qū)域
body: Center(
child:stack
)
),
);
}
}
重疊布局的alignment屬性
alignment
屬性是控制層疊的位置的孔庭,建議在兩個(gè)內(nèi)容進(jìn)行層疊時(shí)使用,它有兩個(gè)值X軸距離和Y軸距離材蛛,值是從0到1的圆到,都是從上層容器的左上角開(kāi)始計(jì)算的
alignment: const FractionalOffset(0.5, 0.8),
CircleAvatar組件的使用
CircleAvatar
這個(gè)常用來(lái)作頭像,組件里面有個(gè)radius的值可以設(shè)置圖片的弧度
new CircleAvatar(
backgroundImage: new NetworkImage('https://ss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2247692397,1189743173&fm=5'),
radius: 100.0,
),
Stack的Position屬性
層疊定位組件
Positioned組件的屬性
- bottom:距離層疊組件下邊的距離
- left:距離層疊組件左邊的距離
- right:距離層疊組件右邊的距離
- top:距離層疊組件上邊的距離
- width:距離層疊組件定位組件的寬度
- height:距離層疊組件定位組件的高度
new Positioned(
bottom:10.0,
right:10.0,
child: new Text('技術(shù)胖'),
)
第05節(jié):卡片組件布局
類似與ViewList卑吭,但是列表會(huì)以物理卡片的形態(tài)進(jìn)行展示
卡片式布局默認(rèn)撐滿整個(gè)外部容器芽淡,如果想要設(shè)置卡片的高度,需要在外部容器就進(jìn)行制定
var card = new Card(
child: Column(
children: <Widget>[
ListTile(
title: Text('湖南省益陽(yáng)市',style:TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text('伊:13710145724'),
leading: new Icon(Icons.account_box,color:Colors.lightBlue),
),
new Divider(),
ListTile(
title: Text('湖南省長(zhǎng)沙市',style:TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text('伊:13710145724'),
leading: new Icon(Icons.account_box,color:Colors.lightBlue),
),
new Divider(),
ListTile(
title: Text('湖南省常德市',style:TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text('伊:13710145724'),
leading: new Icon(Icons.account_box,color:Colors.lightBlue),
),
new Divider(),
],
),
);
//new Divider()分割線
頁(yè)面導(dǎo)航和其他
第01節(jié):一般頁(yè)面導(dǎo)航和返回
RaiseButton按鈕組件
基本屬性:
- child:可以放入容器豆赏,圖標(biāo)挣菲,文字
- onPressed:點(diǎn)擊事件的響應(yīng),一般會(huì)調(diào)用Navigator組件
Navigator.push和Navigator.pop
-
Navigator.push
:是跳轉(zhuǎn)到下一個(gè)頁(yè)面掷邦,他要接受兩個(gè)參數(shù)一個(gè)是上下文context
白胀,另一個(gè)是要跳轉(zhuǎn)的函數(shù) -
Navigator.pop
:是返回到上一個(gè)頁(yè)面,使用時(shí)傳遞一個(gè)context
參數(shù)耙饰,注意纹笼,必須是有上級(jí)頁(yè)面的,也就是說(shuō)上級(jí)頁(yè)面使用了Navigator.push
import 'package:flutter/material.dart';
void main(){
runApp(MaterialApp(
title:'導(dǎo)航演示1',
home:new FirstScreen()
));
}
class FirstScreen extends StatelessWidget{
@override
Widget build(BuildContext context){
return new Scaffold(
appBar: AppBar(title:Text('導(dǎo)航頁(yè)面')),
body:Center(
child:RaisedButton(
child:Text('查看商品詳情頁(yè)面'),
onPressed: (){
Navigator.push(context,new MaterialPageRoute(
builder:(context) =>new SecondScreen())
);
},
)
)
);
}
}
class SecondScreen extends StatelessWidget{
@override
Widget build(BuildContext context){
return Scaffold(
appBar:AppBar(title:Text('技術(shù)胖商品詳情頁(yè)')),
body:Center(
child:RaisedButton(
child:Text('返回'),
onPressed: (){
Navigator.pop(context);
},
))
);
}
}
第02節(jié):導(dǎo)航參數(shù)的傳遞和接受
Awesome Flutter snippets插件的使用:幫助快速生成常用的Flutter代碼片段
聲明數(shù)據(jù)結(jié)構(gòu)類
Dart中可以使用類來(lái)抽象一個(gè)數(shù)據(jù)苟跪,比如我們模仿一個(gè)商品信息廷痘,有商品標(biāo)題和商品描述。定義一個(gè)product類件已,里面有兩個(gè)字符變量笋额,title和description
- title:商品標(biāo)題
- description:商品詳情描述
class Product{
final String title;
final String description;
Product(this.title,this.description)
}
// 主函數(shù),動(dòng)態(tài)函數(shù)
void main(){
runApp(MaterialApp(
title:'數(shù)據(jù)傳遞案例',
home:ProductList(
products:List.generate(
20,
(i)=>Product('商品 $i','這是一個(gè)商品詳情篷扩,編號(hào)為:$i')
),
)
));
}
// 動(dòng)態(tài)生成列表
class ProductList extends StatelessWidget{
final List<Product> products;
ProductList({Key key,@required this.products}):super(key:key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:Text('商品列表')),
body:ListView.builder(
itemCount:products.length,
itemBuilder: (context,index){
return ListTile(
title:Text(products[index].title),
onTap:(){
}
);
},
)
);
}
}
導(dǎo)航參數(shù)的傳遞
使用Navigator
組件兄猩,然后使用路由MaterialPageRouter
傳遞參數(shù)
Navigator.push(
context,
MaterialPageRouter(
builder:(context)=>new ProductDetail(product:products[index])
)
)
第04節(jié):頁(yè)面跳轉(zhuǎn)并返回?cái)?shù)據(jù)
異步請(qǐng)求和等待
Dart的異步請(qǐng)求和等待和ES6的方法很像,直接使用async....await就可以實(shí)現(xiàn)
// async 是啟用異步方法
_navigateToXiaoJieJie(BuildContext context) async{
final result = await Navigator.push(
context,
MaterialPageRouter(
builder:(context)=>Xiaojiejie()
)
);
Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result')));
}
SnackBar的使用
SnackBar
是用戶操作后,顯示提示信息的一個(gè)控件枢冤,類似Tost
鸠姨,會(huì)自動(dòng)隱藏。SnackBar
是以Scaffold
的showSnackBar
方法來(lái)進(jìn)行顯示的
Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result')))
返回?cái)?shù)據(jù)的方式
返回?cái)?shù)據(jù)其實(shí)是特別容易的淹真,只要在返回時(shí)帶第二個(gè)參數(shù)就可以了
Navigator.pop(context,'xxx');//xxx就是返回的參數(shù)
Demo
import 'package:flutter/material.dart';
void main(){
runApp(MaterialApp(
title: '頁(yè)面跳轉(zhuǎn)放回?cái)?shù)據(jù)',
home: FirstPage(),
));
}
class FirstPage extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('找伊大美女要電話號(hào)碼'),
),
body: Center(
child: RouterButton(),
),
);
}
}
class RouterButton extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return RaisedButton(
child: Text('伊伊是大美女'),
onPressed: (){
_navigateToXiaoJieJie(context);
},
);
}
_navigateToXiaoJieJie(BuildContext context) async{ //async是啟用異步方法
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context)=>XiaoJieJie())
);
Scaffold.of(context).showSnackBar(SnackBar(content: Text('$result')));
}
}
class XiaoJieJie extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('我是小姐姐'),
),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
child: Text('大長(zhǎng)腿小姐姐'),
onPressed: (){
Navigator.pop(context,'大長(zhǎng)腿姐姐:13710145724');
},
),
RaisedButton(
onPressed: (){
Navigator.pop(context,'小蠻腰姐姐:13710145724');
},
child: Text('小蠻腰小姐姐'),
)
],
),
),
);
}
}
第05節(jié):靜態(tài)資源和項(xiàng)目圖片的處理
注意:pubspec.yaml文件讶迁,配置項(xiàng)目資源文件,在里面聲明資源文件
assets:
- images/blogtouxiang.jpg
使用項(xiàng)目圖片資源
import 'package:flutter/material.dart';
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Image.asset('images/blogtouxiang.jpg'),
);
}
}
第06節(jié):Flutter客戶端打包
配置APP的圖標(biāo)
項(xiàng)目根目錄/android/app/src/main/res
AndroidManifest.xml文件
這個(gè)文件主要用來(lái)配置APP的名稱核蘸,圖標(biāo)和系統(tǒng)權(quán)限巍糯,所在的目錄在
項(xiàng)目根目錄/android/app/src/main/AndroidManifest.xml
android:label="flutter_app" //配置APP的名稱,支持中文
android:icon="@mipmap/ic_launcher" //APP圖標(biāo)的文件名稱
生成keystore
打包詳情