一.常見布局方式
Row,是水平方向的線性布局(linearlayout)
Column,是垂直方向的線性布局(linearlayout)
Stack,可以理解成為相對布局。
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 中,有兩種方法來添加點擊監(jiān)聽者:
1、如果 widget 本身支持事件監(jiān)測,直接傳遞給它一個函數(shù),并在這個函數(shù)里實現(xiàn)響應方法。例如,RaisedButton、IconButton、OutlineButton、Checkbox、SnackBar、Switch等。
body:Center(
child: OutlineButton(
child: Text('點擊我'),
onPressed: (){
Fluttertoast.showToast(
msg: '你點擊了FlatButton',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1,
);
}),
),
2、如果 widget 本身不支持事件監(jiān)測,則在外面包裹一個 GestureDetector,并給它的 onTap 屬性傳遞一個函數(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 上的其他手勢
屬性 | 取值意義 |
---|---|
onTapDwon | 當按下屏幕時觸發(fā) |
onTap | 當與屏幕短暫地觸碰時觸發(fā),最常用 |
onTapUp | 當用戶停止觸碰屏幕時觸發(fā) |
onTapCancel | 當用戶觸摸屏幕,但沒有完成Tap事件時觸發(fā) |
onDoubleTap | 快速雙擊屏幕時觸發(fā) |
onLongPress | 當長按屏幕時觸發(fā)(與屏幕接觸事件必須超過500ms) |
onPanUpdate | 當在屏幕上移動時觸發(fā) |
onVerticalDragDown | 當手指觸碰屏幕且準備往屏幕垂直方向移動時觸發(fā) |
onVerticalDragStart | 當手指觸碰屏幕且開始往屏幕垂直方向移動時觸發(fā) |
onVerticalDragUpdate | 當手指觸碰屏幕且開始往屏幕垂直方向移動并發(fā)生位移時觸發(fā) |
onVerticalDragEnd | 當用戶完成垂直方向觸摸屏幕時觸發(fā) |
onVerticalDragCancel | 當用戶中斷了onVerticalDragDown時觸發(fā) |
onHorizontalDragDown | 當手指觸摸屏幕且準備往屏幕水平方向移動時觸發(fā) |
onHorizontalDragStart | 當手指觸摸屏幕且開始往屏幕水平方向移動時觸發(fā) |
onHorizontalDragUpdate | 當手指觸摸屏幕且開始往屏幕水平方向移動并發(fā)生位移時觸發(fā) |
onHorizontalDragEnd | 當用戶完成水平方向觸摸屏幕時觸發(fā) |
onHorizontalDragCancel | 當用戶中斷了onHorizontalDragDown時觸發(fā) |
onPanDown | 當用戶觸摸屏幕時觸發(fā) |
onPanStart | 當用戶觸摸屏幕并開始移動時觸發(fā) |
onPanUpdate | 當用戶觸摸屏幕并產(chǎn)生移動時觸發(fā) |
onPanEnd | 當用戶完成觸摸屏幕時觸發(fā) |
onScaleStart | 當用戶觸摸屏幕并開始縮放時觸發(fā) |
onScaleUpdate | 當用戶觸摸屏幕并產(chǎn)生縮放時觸發(fā) |
onScaleEnd | 當用戶完成縮放時觸發(fā) |
三.跳轉頁面(路由和導航)
Flutter 中萬物皆 Widget,頁面自然也是一個 Widget。只不過是一個全屏的 Widget。在flutter中三種頁面跳轉方式:無名路由跳轉(一種動態(tài)構建路由的方式)、命名路由跳轉(一種提前命名路由的方式)
。
1.無名路由跳轉
直接使用使用 Navigator 跳轉頁面,在 Flutter 中,使用 Navigator 來進行頁面跳轉。一個簡單的跳轉頁面的例子:
Navigator.push(
context,
MaterialPageRoute(
// 目標頁面,即一個 Widget
builder: (context) => PageA(),
),
);
或者
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => PageA(),
),
);
關閉A頁面返回到上一個頁面
Navigator.pop(context);
或者
Navigator.of(context).pop();
2.命名路由跳轉
命名路由路由存在的意義在于可以讓我們更方便的導航到想要到達的頁面,便于管理和維護。
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: {
//路由注冊表
"second_page": (BuildContext context) {
return NextPage(ModalRoute.of(context).settings.arguments);
},
"one_route": (BuildContext context) => RandomWord(),
},
);
}
}
可以通過剛剛注冊的頁面名稱來跳轉一個頁面:
Navigator.pushNamed(context, 'one_route');// one_route表示頁面別名
3.接收參數(shù)
傳遞的方式有兩種:
- 在構造方法中傳遞數(shù)據(jù)
- 在Route中傳遞數(shù)據(jù)給下一個頁面
(1)構造方法中傳遞數(shù)據(jù)
需要在接收數(shù)據(jù)的頁面事先定義好構造方法,構造方法中是要接收的參數(shù)。例如:我們在PageB中定義一個構造方法,構造方法中可以定義我們要接收的數(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),
),
);
}
}
跳轉頁面時給PageB傳遞數(shù)據(jù):
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PageB(
data: "要傳遞的數(shù)據(jù)",
),
),
);
(2)將參數(shù)傳遞給指定路由
方式一不是太靈活。Flutter也提供了類似于Android那種通過Intent傳值的方式,在Flutter中我們可以把要傳遞的參數(shù)放到Navigator中,然后傳遞給指定的路由,在接收的頁面提取出需要的參數(shù)即可,這種方式相比方式一更加靈活一些。通過路由進行導航時用到了Navigator.pushNamed(context, pageA);這個方法,實際上這個方法還有第三個參數(shù),
1.首先我們要先定義好要傳遞的數(shù)據(jù)
例如:
我們先定義一個實體類:
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ù)的當前路由。
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入門進階之旅