- 在大前端的开发中,必然存在各种各样与用户交互的情况,比如手指点击,滑动,长按等等;
- 在Flutter中,手势有两个不同的层次:
- 第一层:原始指针事件,描述了屏幕上由触摸板,鼠标,指示笔等触发的指针的位置和移动;
- 第二层:手势识别,这个是在原始事件上的一种封装;
指针事件Pointer
- Pointer表示人机界面的原始数据,一共有四种指针事件:
-
PointerDownEvent
:指针在特定位置与屏幕接触; -
PointerMoveEnent
:指针从屏幕的一个位置移动到另一个位置; -
PointerUpEvent
:指针与屏幕停止接触; -
PointerCancelEvent
:指针因为某些特殊的情况被取消;
-
- Pointer事件的原理:在指针落下时,框架做了一个Hit Test操作,确定与屏幕发生接触的位置上有哪些widget以及分发给最内部的组件去响应;事件会沿着最内部的组件向组件树的根冒泡分发;不能取消或者停止事件的进一步分发;
- 基本上与iOS的事件传递与响应机制的原理一致;
- 案例代码:
import 'package:flutter/material.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SFHomePage(),
);
}
}
class SFHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("商品列表"),
),
body: Center(
child: Listener(
onPointerDown: (event) {
print("手指按下: $event");
print(event.position);
print(event.localPosition);
},
onPointerMove: (event) {
print("手指移动: $event");
},
onPointerUp: (event) {
print("手指抬起: $event");
},
onPointerCancel: (event) {
print("取消 $event");
},
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
)
);
}
}
- 给目标组件
Container
包装一个事件监听Listener
,内部实现各种不同事件的回调方法; -
event.position
:是以屏幕左上角为原点; -
event.localPosition
:是以目标组件Container
的左上角为原点;
手势识别
- 手势是对一系列Pointer的封装,官方建议在开发中尽可能使用手势,而不是Pointer;
手势的分类:
- 点击
- OnTapDown:手指按下
- OnTapUp:手指抬起
- OnTap:点击事件完成
- OnTapCancel:事件取消
- 双击
- OnDoubleTap:快速点击了两次
- 长按
- OnLongPress:在屏幕上保持了一段时间
- 纵向拖拽
- OnVerticalDragStart:指针与屏幕产生接触并可能开始纵向移动;
- OnVerticalDragUpdate:指针与屏幕产生接触,在纵向上发生移动并保持移动;
- OnVerticalDragEnd:指针与屏幕产生接触结束;
- 横向拖拽
- OnHorizontalDragStart:指针与屏幕产生接触并可能开始横向移动;
- OnHorizontalDragUpdate:指针与屏幕产生接触,在横向上发生移动并保持移动;
- OnHorizontalDragEnd:指针与屏幕产生接触结束;
- 移动
- OnPathStart:指针与屏幕产生接触并可能开始横向移动或者纵向移动,如果设置了onHorizontalDragStart或者onVerticalDragStart,该回调会
引发崩溃
; - OnPathUpdate:指针与屏幕产生接触,在横向或者纵向上发生移动并保持移动,如果设置了OnHorizontalDragUpdate或者OnVerticalDragUpdate,该回调会
引发崩溃
; - OnPathEnd:指针与屏幕产生了接触,并以特定的速度移动,此后不再在屏幕上接触发生移动,如果设置了OnHorizontalDragEnd或者OnVerticalDragEnd,该回调会
引发崩溃
;
- OnPathStart:指针与屏幕产生接触并可能开始横向移动或者纵向移动,如果设置了onHorizontalDragStart或者onVerticalDragStart,该回调会
- 案例演练:
import 'package:flutter/material.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SFHomePage(),
);
}
}
class SFHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("商品列表"),
),
body: Center(
child: GestureDetector(
onTapDown: (details) {
print("手指按下");
print(details.globalPosition);
print(details.localPosition);
},
onTapUp: (details) {
print("手指抬起");
},
onTapCancel: () {
print("手势取消");
},
onTap: () {
print("点击");
},
onDoubleTap: () {
print("双击");
},
onLongPress: () {
print("长按");
},
child: Container(
width: 200,
height: 200,
color: Colors.greenAccent,
),
),
)
);
}
}
- 给目标组件Container,包装一个
GestureDetector
手势管理器,实现各种手势的监听回调函数;
案例演练:组件重叠显示时的手势识别
import 'package:flutter/material.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SFHomePage(),
);
}
}
class SFHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("商品列表"),
),
body: Center(
child: GestureDetector(
onTapDown: (details) {
print("outside click");
},
child: Container(
width: 200,
height: 200,
color: Colors.red,
alignment: Alignment.center,
child: GestureDetector(
onTapDown: (details) {
print("inside click");
},
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
),
),
),
)
);
}
}
- 运行效果如下所示:
- 两个组件都加了手势监听,当点击绿色组件的时候,红色组件偶尔也会出现监听回调,为了解决这个问题,改变组件的布局层级,利用Stack组件,代码如下:
import 'package:flutter/material.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SFHomePage(),
);
}
}
class SFHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("商品列表"),
),
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
GestureDetector(
onTapDown: (details) {
print("red click");
},
child: Container(
width: 200,
height: 200,
color: Colors.red,
alignment: Alignment.center,
)
),
GestureDetector(
onTapDown: (details) {
print("greenAccent click");
},
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
)
],
)
)
);
}
}
当点击绿色组件的时候,只有绿色组件响应手势,红色组件不会响应;
现在想要实现:当点击绿色组件时,只有红色组件响应手势事件,即实现了事件的穿透效果,代码如下:
import 'package:flutter/material.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SFHomePage(),
);
}
}
class SFHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("商品列表"),
),
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
GestureDetector(
onTapDown: (details) {
print("red click");
},
child: Container(
width: 200,
height: 200,
color: Colors.red,
alignment: Alignment.center,
)
),
IgnorePointer(
child: GestureDetector(
onTapDown: (details) {
print("greenAccent click");
},
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
),
)
],
)
)
);
}
}
- 给绿色组件 最外层包裹了一个
IgnorePointer
,实现了手势事件的忽略;
跨组件事件的传递
- 使用第三方库
event_bus
实现跨组件事件的传递; - 工程中引用
event_bus
:
dependencies:
event_bus: ^1.1.1
- 使用步骤:
1.创建全局的EventBus对象;
2.发出事件;
- 监听事件的类型;
- 案例代码如下:
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';
//1.创建全局的EventBus对象
final EventBus eventBus = EventBus();
class SFUserInfo {
String name;
int level;
SFUserInfo(this.name,this.level);
}
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SFHomePage(),
);
}
}
class SFHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("商品列表"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SFButton(),
SFText(),
],
),
)
);
}
}
class SFButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
child: Text("按钮"),
onPressed: () {
print("点击按钮");
//2.发出事件
final userInfo = SFUserInfo("liyanyan",100);
eventBus.fire(userInfo);
},
);
}
}
class SFText extends StatefulWidget {
@override
_SFTextState createState() => _SFTextState();
}
class _SFTextState extends State<SFText> {
String _message = "Hello World";
@override
void initState() {
// TODO: implement initState
super.initState();
//3.监听事件的类型
eventBus.on<SFUserInfo>().listen((data) {
print(data.name);
print(data.level);
_message = "${data.name} -- ${data.level}";
});
}
@override
Widget build(BuildContext context) {
return Text("Hello World!!!",style: TextStyle(fontSize: 25));
}
}
路由管理
- 路由的概念由来已久,包括
网络路由
,后端路由
,到现在广为流行的前端路由
; - 无论路由的概念如何应用,它的核心是一个
路由映射表
,例如名字detail
映射到DetailPage
页面; - 有了映射表之后,我们就可以方便的根据名字来完成路由的转发,即页面跳转;
- 在Flutter中,路由管理主要有两个类
Route
与Navigator
Route
- Route:一个页面要想被路由统一管理,必须包装为一个Route,Route是一个抽象类,所以只能实例化其子类;
-
MaterialPageRoute
是使用最广泛的路由,其在不同的平台会有不同的表现:- 在Android平台,打开一个页面从屏幕底部滑到屏幕顶部;
- 在iOS平台,打开一个页面从屏幕右侧滑到屏幕左侧;
- 在iOS平台还可以使用
CupertinoPageRoute
Navigator
- Navigator:管理所有的Route的widget,通过一个栈进行管理的;
- 在开发中我们不需要手动去创建一个Navigator,因为在开发中使用的MaterialApp,CupertinoApp,WidgetsApp它们默认是有插入Navigator的,所以,我们在需要的时候,只需要直接使用即可;
路由的基本使用
- 需求:首页与详情页两个页面,当首页->详情页 携带数据过去,当详情页 -> 首页 传递数据给首页,代码如下:
- 首页代码:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:learn_flutter_01/day02/SFDetail.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SFHomePage(),
);
}
}
class SFHomePage extends StatefulWidget {
@override
_SFHomePageState createState() => _SFHomePageState();
}
class _SFHomePageState extends State<SFHomePage> {
String homeMessage = "default message";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("首页"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(homeMessage,style: TextStyle(fontSize: 20)),
RaisedButton(
child: Text("跳转到详情页面"),
onPressed: () {
goToDetail(context);
},
)
],
)
)
);
}
void goToDetail(BuildContext ctx) {
Future result = Navigator.of(ctx).push(MaterialPageRoute(
builder: (ctx) {
return SFDetail("liyanyan");
}
));
result.then((value) {
print(value);
setState(() {
homeMessage = value;
});
});
}
}
- 详情页代码:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SFDetail extends StatelessWidget {
final String message;
SFDetail(this.message);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("详情页"),
leading: IconButton(
icon: Icon(Icons.backspace),
onPressed: () => backHomePage(context),
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(message,style: TextStyle(fontSize: 20)),
RaisedButton(
child: Text("返回首页"),
onPressed: () => backHomePage(context),
)
],
)
),
);
}
void backHomePage(BuildContext ctx) {
Navigator.of(ctx).pop("xie shen fang");
}
}
- 首页 -> 详情页 创建
MaterialPageRoute
路由
void goToDetail(BuildContext ctx) {
Future result = Navigator.of(ctx).push(MaterialPageRoute(
builder: (ctx) {
return SFDetail("liyanyan");
}
));
result.then((value) {
print(value);
setState(() {
homeMessage = value;
});
});
}
- 详情页 -> 首页
void backHomePage(BuildContext ctx) {
Navigator.of(ctx).pop("xie shen fang");
}
- 在详情页
去除了系统提供的返回按钮
,使用自己的按钮; - 在详情页,使用系统的提供返回的按钮,但是我们要重写点击事件的逻辑,可以使用
WillPopScope
,如下所示:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SFDetail extends StatelessWidget {
final String message;
SFDetail(this.message);
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
//当返回为true时,可以自动返回;
//当返回为false时,不能自动返回首页,需要我们手写代码进行返回;
backHomePage(context);
return Future.value(false);
},
child: Scaffold(
appBar: AppBar(
title: Text("详情页"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(message,style: TextStyle(fontSize: 20)),
RaisedButton(
child: Text("返回首页"),
onPressed: () => backHomePage(context),
)
],
)
),
),
);
}
void backHomePage(BuildContext ctx) {
Navigator.of(ctx).pop("xie shen fang");
}
}
onWillPop
参数,传入函数,其函数的返回值为Future.value(bool)当bool = true时,可以自动返回;
当bool = false时,不能自动返回首页,需要我们手写代码进行返回;
上述采用的简单的路由跳转,下面介绍路由表映射的跳转,再新建一个
SFAbout
页面:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SFAbout extends StatelessWidget {
static const String routeName = "SFAbout";
@override
Widget build(BuildContext context) {
final message = ModalRoute.of(context).settings.arguments as String;
return Scaffold(
appBar: AppBar(
title: Text("关于页面"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(message),
RaisedButton(
child: Text("返回首页"),
onPressed: () {
},
)
],
),
),
);
}
}
- 首页代码改造如下:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:learn_flutter_01/day02/SFAbout.dart';
import 'package:learn_flutter_01/day02/SFDetail.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
SFHomePage.routeName : (ctx) => SFHomePage(),
SFAbout.routeName : (ctx) => SFAbout()
},
initialRoute: SFHomePage.routeName
);
}
}
class SFHomePage extends StatefulWidget {
static const String routeName = "/";
@override
_SFHomePageState createState() => _SFHomePageState();
}
class _SFHomePageState extends State<SFHomePage> {
String homeMessage = "default message";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("首页"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(homeMessage,style: TextStyle(fontSize: 20)),
RaisedButton(
child: Text("跳转到详情页面"),
onPressed: () {
goToDetail(context);
},
),
RaisedButton(
child: Text("跳转到关于页面"),
onPressed: () {
goToAbout(context);
},
)
],
)
)
);
}
void goToDetail(BuildContext ctx) {
Future result = Navigator.of(ctx).push(MaterialPageRoute(
builder: (ctx) {
return SFDetail("liyanyan");
}
));
result.then((value) {
print(value);
setState(() {
homeMessage = value;
});
});
}
void goToAbout(BuildContext ctx) {
Future result = Navigator.of(context).pushNamed(SFAbout.routeName,arguments: "liyanyan");
result.then((value) {
print(value);
});
}
}
- 在
MaterialApp
组件中,传入routes
与initialRoute
两个参数,其中routes
表示路由表,initialRoute
表示App的首页路由为SFHomePage(); - 在首页 跳转 SFAbout页面时,执行:
Navigator.of(context).pushNamed(SFAbout.routeName,arguments: "liyanyan")
其中arguments为携带的数据; - 在SFAbout页面接收到首页的数据:
final message = ModalRoute.of(context).settings.arguments as String
-
SFDetail
页面的构造函数,定义了一个入参,那么在MaterialApp
的routes
,写路由映射时,不能传参的,这时就引入了onGenerateRoute
,再次生成一个新的路由,可传参的,实现如下:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:learn_flutter_01/day02/SFAbout.dart';
import 'package:learn_flutter_01/day02/SFDetail.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
SFHomePage.routeName : (ctx) => SFHomePage(),
SFAbout.routeName : (ctx) => SFAbout()
},
initialRoute: SFHomePage.routeName,
onGenerateRoute: (setttings) {
if (setttings.name == SFDetail.routeName) {
return MaterialPageRoute(
builder: (ctx) {
return SFDetail(setttings.arguments);
}
);
}
return null;
}
);
}
}
class SFHomePage extends StatefulWidget {
static const String routeName = "/";
@override
_SFHomePageState createState() => _SFHomePageState();
}
class _SFHomePageState extends State<SFHomePage> {
String homeMessage = "default message";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("首页"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(homeMessage,style: TextStyle(fontSize: 20)),
RaisedButton(
child: Text("跳转到详情页面"),
onPressed: () {
goToDetail(context);
},
),
RaisedButton(
child: Text("跳转到关于页面"),
onPressed: () {
goToAbout(context);
},
),
RaisedButton(
child: Text("跳转到详情页面"),
onPressed: () {
goToDetail2(context);
},
)
],
)
)
);
}
void goToDetail(BuildContext ctx) {
Future result = Navigator.of(ctx).push(MaterialPageRoute(
builder: (ctx) {
return SFDetail("liyanyan");
}
));
result.then((value) {
print(value);
setState(() {
homeMessage = value;
});
});
}
void goToAbout(BuildContext ctx) {
Future result = Navigator.of(context).pushNamed(SFAbout.routeName,arguments: "liyanyan");
result.then((value) {
print(value);
});
}
void goToDetail2(BuildContext ctx) {
Navigator.of(context).pushNamed(SFDetail.routeName,arguments: "123");
}
}
- 如果跳转的页面 在路由映射表中 没有注册,就会跳转报错,一般我们定义一个错误页面
SFUnKnownPage
,代码如下:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SFUnKnownPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("错误页面"),
),
body: Center(
child: Text("错误页面"),
),
);
}
}
- 然后在
MaterialApp
中,新增参数onUnknownRoute
,传入错误页面的路由,如下所示:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:learn_flutter_01/day02/SFAbout.dart';
import 'package:learn_flutter_01/day02/SFDetail.dart';
import 'package:learn_flutter_01/day02/SFUnknownPage.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
SFHomePage.routeName : (ctx) => SFHomePage(),
SFAbout.routeName : (ctx) => SFAbout()
},
initialRoute: SFHomePage.routeName,
onGenerateRoute: (setttings) {
if (setttings.name == SFDetail.routeName) {
return MaterialPageRoute(
builder: (ctx) {
return SFDetail(setttings.arguments);
}
);
}
return null;
},
onUnknownRoute: (settings) {
return MaterialPageRoute(
builder: (ctx) {
return SFUnKnownPage();
}
);
},
);
}
}
class SFHomePage extends StatefulWidget {
static const String routeName = "/";
@override
_SFHomePageState createState() => _SFHomePageState();
}
class _SFHomePageState extends State<SFHomePage> {
String homeMessage = "default message";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("首页"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(homeMessage,style: TextStyle(fontSize: 20)),
RaisedButton(
child: Text("跳转到详情页面"),
onPressed: () {
goToDetail(context);
},
),
RaisedButton(
child: Text("跳转到关于页面"),
onPressed: () {
goToAbout(context);
},
),
RaisedButton(
child: Text("跳转到详情页面"),
onPressed: () {
goToDetail2(context);
},
),
RaisedButton(
child: Text("跳转到设置页面"),
onPressed: () {
goToAbou2(context);
},
)
],
)
)
);
}
void goToDetail(BuildContext ctx) {
Future result = Navigator.of(ctx).push(MaterialPageRoute(
builder: (ctx) {
return SFDetail("liyanyan");
}
));
result.then((value) {
print(value);
setState(() {
homeMessage = value;
});
});
}
void goToAbout(BuildContext ctx) {
Future result = Navigator.of(context).pushNamed(SFAbout.routeName,arguments: "liyanyan");
result.then((value) {
print(value);
});
}
void goToDetail2(BuildContext ctx) {
Navigator.of(context).pushNamed(SFDetail.routeName,arguments: "123");
}
void goToAbou2(BuildContext ctx) {
///setting为定义的页面 跳转页面会直接报错
Navigator.of(context).pushNamed("/settings");
}
}
setting为定义的页面 跳转页面会直接报错;
代码封装,将有关的路由封装到一个专门处理路由的类
SFRouter
,如下所示:
import 'package:flutter/material.dart';
import 'package:learn_flutter_01/day02/SFAbout.dart';
import 'package:learn_flutter_01/day02/SFDetail.dart';
import 'package:learn_flutter_01/main.dart';
import '../SFUnknownPage.dart';
class SFRouter {
static final Map<String,WidgetBuilder> routers = {
SFHomePage.routeName : (ctx) => SFHomePage(),
SFAbout.routeName : (ctx) => SFAbout(),
};
static final String initialRoute = SFHomePage.routeName;
static final RouteFactory generateRoute = (settings) {
if (settings.name == SFDetail.routeName) {
return MaterialPageRoute(
builder: (ctx) {
return SFDetail(settings.arguments);
}
);
}
return null;
};
static final RouteFactory unknownRoute = (settings) {
return MaterialPageRoute(
builder: (ctx) {
return SFUnKnownPage();
}
);
};
}
- 首页调用路由就变得十分简洁了,如下所示:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:learn_flutter_01/day02/SFAbout.dart';
import 'package:learn_flutter_01/day02/SFDetail.dart';
import 'package:learn_flutter_01/day02/SFUnknownPage.dart';
import 'package:learn_flutter_01/day02/router/SFRouter.dart';
main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: SFRouter.routers,
initialRoute: SFRouter.initialRoute,
onGenerateRoute: SFRouter.generateRoute,
onUnknownRoute: SFRouter.unknownRoute,
);
}
}
class SFHomePage extends StatefulWidget {
static const String routeName = "/";
@override
_SFHomePageState createState() => _SFHomePageState();
}
class _SFHomePageState extends State<SFHomePage> {
String homeMessage = "default message";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("首页"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(homeMessage,style: TextStyle(fontSize: 20)),
RaisedButton(
child: Text("跳转到详情页面"),
onPressed: () {
goToDetail(context);
},
),
RaisedButton(
child: Text("跳转到关于页面"),
onPressed: () {
goToAbout(context);
},
),
RaisedButton(
child: Text("跳转到详情页面"),
onPressed: () {
goToDetail2(context);
},
),
RaisedButton(
child: Text("跳转到设置页面"),
onPressed: () {
goToAbou2(context);
},
)
],
)
)
);
}
void goToDetail(BuildContext ctx) {
Future result = Navigator.of(ctx).push(MaterialPageRoute(
builder: (ctx) {
return SFDetail("liyanyan");
}
));
result.then((value) {
print(value);
setState(() {
homeMessage = value;
});
});
}
void goToAbout(BuildContext ctx) {
Future result = Navigator.of(context).pushNamed(SFAbout.routeName,arguments: "liyanyan");
result.then((value) {
print(value);
});
}
void goToDetail2(BuildContext ctx) {
Navigator.of(context).pushNamed(SFDetail.routeName,arguments: "123");
}
void goToAbou2(BuildContext ctx) {
///setting为定义的页面 跳转页面会直接报错
Navigator.of(context).pushNamed("/settings");
}
}