一.常見布局方式
Row,是水平方向的線性布局(linearlayout)
Column,是垂直方向的線性布局(linearlayout)
Stack,可以理解成為相對(duì)布局。
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 Column(
children: <Widget>[
new Text('Text 1'),
new Text('Text 2'),
new Text('Text 3')
],),),),);}
}
二.事件
在 Flutter 中,有兩種方法來添加點(diǎn)擊監(jiān)聽者:
1、如果 widget 本身支持事件監(jiān)測(cè),直接傳遞給它一個(gè)函數(shù),并在這個(gè)函數(shù)里實(shí)現(xiàn)響應(yīng)方法。例如,RaisedButton、IconButton、OutlineButton、Checkbox、SnackBar、Switch等。
body:Center(
child: OutlineButton(
child: Text('點(diǎn)擊我'),
onPressed: (){
Fluttertoast.showToast(
msg: '你點(diǎn)擊了FlatButton',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1,
);
}),
),
2、如果 widget 本身不支持事件監(jiān)測(cè),則在外面包裹一個(gè) GestureDetector,并給它的 onTap 屬性傳遞一個(gè)函數(shù):
class SampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GestureDetector(
child: FlutterLogo(
size: 200.0,
),
onTap: () {
print("tap");
},
),
),
);
}
}
3、widget 上的其他手勢(shì)
| 屬性 | 取值意義 |
|---|---|
| onTapDwon | 當(dāng)按下屏幕時(shí)觸發(fā) |
| onTap | 當(dāng)與屏幕短暫地觸碰時(shí)觸發(fā),最常用 |
| onTapUp | 當(dāng)用戶停止觸碰屏幕時(shí)觸發(fā) |
| onTapCancel | 當(dāng)用戶觸摸屏幕,但沒有完成Tap事件時(shí)觸發(fā) |
| onDoubleTap | 快速雙擊屏幕時(shí)觸發(fā) |
| onLongPress | 當(dāng)長(zhǎng)按屏幕時(shí)觸發(fā)(與屏幕接觸事件必須超過500ms) |
| onPanUpdate | 當(dāng)在屏幕上移動(dòng)時(shí)觸發(fā) |
| onVerticalDragDown | 當(dāng)手指觸碰屏幕且準(zhǔn)備往屏幕垂直方向移動(dòng)時(shí)觸發(fā) |
| onVerticalDragStart | 當(dāng)手指觸碰屏幕且開始往屏幕垂直方向移動(dòng)時(shí)觸發(fā) |
| onVerticalDragUpdate | 當(dāng)手指觸碰屏幕且開始往屏幕垂直方向移動(dòng)并發(fā)生位移時(shí)觸發(fā) |
| onVerticalDragEnd | 當(dāng)用戶完成垂直方向觸摸屏幕時(shí)觸發(fā) |
| onVerticalDragCancel | 當(dāng)用戶中斷了onVerticalDragDown時(shí)觸發(fā) |
| onHorizontalDragDown | 當(dāng)手指觸摸屏幕且準(zhǔn)備往屏幕水平方向移動(dòng)時(shí)觸發(fā) |
| onHorizontalDragStart | 當(dāng)手指觸摸屏幕且開始往屏幕水平方向移動(dòng)時(shí)觸發(fā) |
| onHorizontalDragUpdate | 當(dāng)手指觸摸屏幕且開始往屏幕水平方向移動(dòng)并發(fā)生位移時(shí)觸發(fā) |
| onHorizontalDragEnd | 當(dāng)用戶完成水平方向觸摸屏幕時(shí)觸發(fā) |
| onHorizontalDragCancel | 當(dāng)用戶中斷了onHorizontalDragDown時(shí)觸發(fā) |
| onPanDown | 當(dāng)用戶觸摸屏幕時(shí)觸發(fā) |
| onPanStart | 當(dāng)用戶觸摸屏幕并開始移動(dòng)時(shí)觸發(fā) |
| onPanUpdate | 當(dāng)用戶觸摸屏幕并產(chǎn)生移動(dòng)時(shí)觸發(fā) |
| onPanEnd | 當(dāng)用戶完成觸摸屏幕時(shí)觸發(fā) |
| onScaleStart | 當(dāng)用戶觸摸屏幕并開始縮放時(shí)觸發(fā) |
| onScaleUpdate | 當(dāng)用戶觸摸屏幕并產(chǎn)生縮放時(shí)觸發(fā) |
| onScaleEnd | 當(dāng)用戶完成縮放時(shí)觸發(fā) |
三.跳轉(zhuǎn)頁面(路由和導(dǎo)航)
Flutter 中萬物皆 Widget,頁面自然也是一個(gè) Widget。只不過是一個(gè)全屏的 Widget。在flutter中三種頁面跳轉(zhuǎn)方式:無名路由跳轉(zhuǎn)(一種動(dòng)態(tài)構(gòu)建路由的方式)、命名路由跳轉(zhuǎn)(一種提前命名路由的方式)。
1.無名路由跳轉(zhuǎn)
直接使用使用 Navigator 跳轉(zhuǎn)頁面,在 Flutter 中,使用 Navigator 來進(jìn)行頁面跳轉(zhuǎn)。一個(gè)簡(jiǎn)單的跳轉(zhuǎn)頁面的例子:
Navigator.push(
context,
MaterialPageRoute(
// 目標(biāo)頁面,即一個(gè) Widget
builder: (context) => PageA(),
),
);
或者
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => PageA(),
),
);
關(guān)閉A頁面返回到上一個(gè)頁面
Navigator.pop(context);
或者
Navigator.of(context).pop();
2.命名路由跳轉(zhuǎn)
命名路由路由存在的意義在于可以讓我們更方便的導(dǎo)航到想要到達(dá)的頁面,便于管理和維護(hù)。
void main() => runApp(MyApp());//單行函數(shù)調(diào)用寫法
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "My App Title",
theme: ThemeData(primaryColor: Colors.green),
//home: RandomWord(),//初始路由頁面一
initialRoute: "one_route",//初始路由頁面二
routes: {
//路由注冊(cè)表
"second_page": (BuildContext context) {
return NextPage(ModalRoute.of(context).settings.arguments);
},
"one_route": (BuildContext context) => RandomWord(),
},
);
}
}
可以通過剛剛注冊(cè)的頁面名稱來跳轉(zhuǎn)一個(gè)頁面:
Navigator.pushNamed(context, 'one_route');// one_route表示頁面別名
3.接收參數(shù)
傳遞的方式有兩種:
- 在構(gòu)造方法中傳遞數(shù)據(jù)
- 在Route中傳遞數(shù)據(jù)給下一個(gè)頁面
(1)構(gòu)造方法中傳遞數(shù)據(jù)
需要在接收數(shù)據(jù)的頁面事先定義好構(gòu)造方法,構(gòu)造方法中是要接收的參數(shù)。例如:我們?cè)赑ageB中定義一個(gè)構(gòu)造方法,構(gòu)造方法中可以定義我們要接收的數(shù)據(jù):
import 'package:flutter/material.dart';
class PageB extends StatelessWidget {
String data;
PageB({this.data});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("B頁面"),
leading: InkWell(
onTap: () {
Navigator.pop(pageContext);
},
child: Icon(
Icons.arrow_back,
),
),
),
body: Center(
child: Text(data),
),
);
}
}
跳轉(zhuǎn)頁面時(shí)給PageB傳遞數(shù)據(jù):
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PageB(
data: "要傳遞的數(shù)據(jù)",
),
),
);
(2)將參數(shù)傳遞給指定路由
方式一不是太靈活。Flutter也提供了類似于Android那種通過Intent傳值的方式,在Flutter中我們可以把要傳遞的參數(shù)放到Navigator中,然后傳遞給指定的路由,在接收的頁面提取出需要的參數(shù)即可,這種方式相比方式一更加靈活一些。通過路由進(jìn)行導(dǎo)航時(shí)用到了Navigator.pushNamed(context, pageA);這個(gè)方法,實(shí)際上這個(gè)方法還有第三個(gè)參數(shù),
1.首先我們要先定義好要傳遞的數(shù)據(jù)
例如:
我們先定義一個(gè)實(shí)體類:
class People {
String name;
int age;
People(this.name, this.age);
}
2.傳遞參數(shù)
將參數(shù)數(shù)據(jù)傳遞給PageB,可以有如下四種傳參方式,效果都一樣
Navigator.pushNamed(
context,
pageB,
arguments: People("yzq", 25),//要傳遞的數(shù)據(jù)
);
或者
Navigator.of(context).pushNamed(pageB, arguments: People("yzq", 25));
或者·
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PageB(),
settings: RouteSettings(
arguments: People("yuzhiqiang", 26),
),
),
);
或者
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => PageB(),
settings: RouteSettings(
arguments: People("yuzhiqiang", 26),
)
),
);
3.接收參數(shù)
在PageB接收數(shù)據(jù),接收數(shù)據(jù)要通過 ModalRoute.of 方法。此方法返回帶有參數(shù)的當(dāng)前路由。
import 'package:flutter/material.dart';
import 'package:flutter_router/people.dart';
class PageB extends StatelessWidget {
@override
Widget build(BuildContext context) {
/*獲取傳遞過來的參數(shù)*/
People _people = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text("B頁面"),
leading: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.arrow_back,
),
),
),
body: Center(
child: Text("姓名:${_people.name},年齡:${_people.age}"),
),
);
}
}
更多信息參考 Navigator API
Flutter布局方式總
Flutter 初嘗試:入門教程
GSY Flutter 系列專欄
flutter中文網(wǎng)
Flutter入門進(jìn)階之旅