一.常见布局方式
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: [
new Text('Text 1'),
new Text('Text 2'),
new Text('Text 3')
],),),),);}
}
二.事件
在 Flutter 中,有两种方法来添加点击监听者:
1、如果 widget 本身支持事件监测,直接传递给它一个函数,并在这个函数里实现响应方法。例如,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 本身不支持事件监测,则在外面包裹一个 GestureDetector,并给它的 onTap 属性传递一个函数:
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 | 当按下屏幕时触发 |
onTap | 当与屏幕短暂地触碰时触发,最常用 |
onTapUp | 当用户停止触碰屏幕时触发 |
onTapCancel | 当用户触摸屏幕,但没有完成Tap事件时触发 |
onDoubleTap | 快速双击屏幕时触发 |
onLongPress | 当长按屏幕时触发(与屏幕接触事件必须超过500ms) |
onPanUpdate | 当在屏幕上移动时触发 |
onVerticalDragDown | 当手指触碰屏幕且准备往屏幕垂直方向移动时触发 |
onVerticalDragStart | 当手指触碰屏幕且开始往屏幕垂直方向移动时触发 |
onVerticalDragUpdate | 当手指触碰屏幕且开始往屏幕垂直方向移动并发生位移时触发 |
onVerticalDragEnd | 当用户完成垂直方向触摸屏幕时触发 |
onVerticalDragCancel | 当用户中断了onVerticalDragDown时触发 |
onHorizontalDragDown | 当手指触摸屏幕且准备往屏幕水平方向移动时触发 |
onHorizontalDragStart | 当手指触摸屏幕且开始往屏幕水平方向移动时触发 |
onHorizontalDragUpdate | 当手指触摸屏幕且开始往屏幕水平方向移动并发生位移时触发 |
onHorizontalDragEnd | 当用户完成水平方向触摸屏幕时触发 |
onHorizontalDragCancel | 当用户中断了onHorizontalDragDown时触发 |
onPanDown | 当用户触摸屏幕时触发 |
onPanStart | 当用户触摸屏幕并开始移动时触发 |
onPanUpdate | 当用户触摸屏幕并产生移动时触发 |
onPanEnd | 当用户完成触摸屏幕时触发 |
onScaleStart | 当用户触摸屏幕并开始缩放时触发 |
onScaleUpdate | 当用户触摸屏幕并产生缩放时触发 |
onScaleEnd | 当用户完成缩放时触发 |
三.跳转页面(路由和导航)
Flutter 中万物皆 Widget,页面自然也是一个 Widget。只不过是一个全屏的 Widget。在flutter中三种页面跳转方式:无名路由跳转(一种动态构建路由的方式)、命名路由跳转(一种提前命名路由的方式)
。
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());//单行函数调用写法
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.接收参数
传递的方式有两种:
- 在构造方法中传递数据
- 在Route中传递数据给下一个页面
(1)构造方法中传递数据
需要在接收数据的页面事先定义好构造方法,构造方法中是要接收的参数。例如:我们在PageB中定义一个构造方法,构造方法中可以定义我们要接收的数据:
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传递数据:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PageB(
data: "要传递的数据",
),
),
);
(2)将参数传递给指定路由
方式一不是太灵活。Flutter也提供了类似于Android那种通过Intent传值的方式,在Flutter中我们可以把要传递的参数放到Navigator中,然后传递给指定的路由,在接收的页面提取出需要的参数即可,这种方式相比方式一更加灵活一些。通过路由进行导航时用到了Navigator.pushNamed(context, pageA);这个方法,实际上这个方法还有第三个参数,
1.首先我们要先定义好要传递的数据
例如:
我们先定义一个实体类:
class People {
String name;
int age;
People(this.name, this.age);
}
2.传递参数
将参数数据传递给PageB,可以有如下四种传参方式,效果都一样
Navigator.pushNamed(
context,
pageB,
arguments: People("yzq", 25),//要传递的数据
);
或者
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.接收参数
在PageB接收数据,接收数据要通过 ModalRoute.of 方法。此方法返回带有参数的当前路由。
import 'package:flutter/material.dart';
import 'package:flutter_router/people.dart';
class PageB extends StatelessWidget {
@override
Widget build(BuildContext context) {
/*获取传递过来的参数*/
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中文网
Flutter入门进阶之旅