Flutter从入门到实战
一共分为23个系列
①(Flutter、Dart环境搭建篇) 共3个内容 已更新
②(Dart语法1 篇) 共4个内容 已更新
③(Dart语法2 篇) 共2个内容 已更新
④(Flutter案例开发篇) 共4个内容 已更新
⑤(Flutter的StatelessWidget 共3个内容 已更新
⑥(Flutter的基础Widget篇) 共2个内容 已更新
⑦(布局Widget篇) 共1个内容 已更新
⑧(Flex、Row、Column以及Flexible、Stack篇) 共1个内容 已更新
⑨(滚动的Widget篇) 共4个内容 已更新
⑩(Dart的Future和网络篇) 共3个内容 已更新
⑪(豆瓣案例-1篇) 共3个内容 已更新
⑫(豆瓣案例-2篇) 共3个内容 已更新
⑬(Flutter渲染流程篇) 共3个内容 已更新
⑭(状态管理篇) 共3个内容 已更新
⑭(状态管理篇) 共3个内容 已更新
⑮(Flutter事件监听-以及路由使用篇) 共2个内容 已更新
官方文档说明
官方视频教程
Flutter的YouTube视频教程-小部件

⑮、Flutter事件监听篇
📚小贴士、FittedBox 做适配使用(比较实用)
官方文档
1.1 看一下我们之前写豆瓣首页的项目
比如星星的Widget。如果我把整体的Size调大。他会超出屏幕的范围。
我们如何修改?
- 调整字体的大小
- 使用FittedBox 他会进行一个整体的压缩
- 使用第三方库 进行一个比例系数 ,也可自己去实现一个rpx
比如 我希望一个图片
在iPhone5 是 90*90
在iPhone6 是 100 * 100
在iPhone6sPlus 是 110 *110
1.1 项目原始图
Widget buildContentInfoRate(){
return Row(
children: [
YHStarRating(rating: movie.rate,size: 40,),
SizedBox(width: 6,),
Text("${movie.rate}",style: TextStyle(fontSize:12)),
],
);
}

1.2 效果图 - 调整Size 超出屏幕范围
Widget buildContentInfoRate(){
return Row(
children: [
YHStarRating(rating: movie.rate,size: 300,),
SizedBox(width: 6,),
Text("${movie.rate}",style: TextStyle(fontSize:20)),
],
);
}

1.3 效果图 - 使用FittedBox 进行适配
Widget buildContentInfoRate(){
// FittedBox 是用来做适配的 整体做一个压缩
return FittedBox(
child: Row(
children: [
YHStarRating(rating: movie.rate,size: 300,),
SizedBox(width: 6,),
Text("${movie.rate}",style: TextStyle(fontSize:20)),
],
),
);
}

①、Flutter的事件监听
1、指针事件Pointer
PointerDownEvent
PointerMoveEvent
PointerUpEvent
PointerCancelEvent
1.1 指针事件Pointer的使用
使用指针事件 必须使用系统的
ListenerWidget包裹
1.2 代码实现 - 指针事件Pointer的使用
import 'package:flutter/material.dart'; // runApp在这个material库里面
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: YHiOSHomePage(),
);
}
}
class YHiOSHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("学习模板_Widget"),
),
body: Listener(
onPointerDown: (event){
print("指针按下$event");
print(event.position); // 获取指针在当前屏幕的位置
print(event.localPosition); // 获取指针在当前Wdiget的位置
},
onPointerMove: (event){
print("指针移动$event");
},
onPointerUp: (event){
print("指针抬起$event");
},
child: Center(
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
),
),
);
}
}
1.3 效果图 - 指针事件Pointer的使用

2、 手势事件 GestureDetector
1.手势
手势的监听有
- 按下
- 抬起
- 取消
- 点击
- 长按
- 双击
等等
1.2 代码实现 - GestureDetector 的使用
class GestureDetectorDemoWidget extends StatelessWidget {
const GestureDetectorDemoWidget({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (details){
print("手指按下");
print(details.globalPosition);// 屏幕的所在位置
print(details.localPosition); // 当前widget的所在位置
},
onTapUp: (details){
print("手指抬起");
},
onTapCancel: (){
print("手势取消");
},
onTap: (){
print("手势点击");
},
onDoubleTap: (){
print("手势双击");
},
onLongPress: (){
print("手势长按");
},
child: Center(
child: Container(
width: 200,
height: 200,
color: Colors.pink,
)
),
);
}
}
1.3、手势案例 - GestureDetector 叠加Widget问题 会出现内外穿透问题
使用Stack进行包裹
可以解决 GestureDetector 点击事件的穿透问题
1.3.1 不使用Stack 可能会引发点击事件的穿透 偶尔发送
可以使用
behavior: HitTestBehavior.opaque, // 解决外部穿透点击问题 但是可能还是会出现问题
1.3.1 代码 - 不使用Stack 可能会引发点击事件的穿透 偶尔发送
class YHiOSHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("手势模板_Widget"),
),
body: Center(
child: GestureDetector(
onTapDown: (detils){
print("outer click 内部点");
},
child: Container(
width: 200,
height: 200,
color: Colors.red,
alignment: Alignment.center, // 包裹下一个Container 必须使用alignment
child: GestureDetector(
behavior: HitTestBehavior.opaque, // 解决外部穿透点击问题 但是可能还是会出现问题
onTapDown: (detils){
print("inner click 内部点");
},
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
),
),
),
);
}
}
1.3.2 使用Stack 包裹 GestureDetector 单独分离出来
1.3.2 代码 - 使用Stack 包裹 GestureDetector 单独分离出来
class GestureDetectorStackWidget extends StatelessWidget {
const GestureDetectorStackWidget({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
// 使用Stack包裹手势 单独分离出来 这样就不会出现内外部点击穿透问题
child:Stack(
alignment: Alignment.center,
children: [
GestureDetector(
onTapDown: (detils){
print("outer click 内部点");
},
child: Container(
width: 200,
height: 200,
color: Colors.red,
alignment: Alignment.center, // 包裹下一个Container 必须使用alignment
),
),
GestureDetector(
behavior: HitTestBehavior.opaque, // 解决外部穿透点击问题 但是可能还是会出现问题
onTapDown: (detils){
print("inner click 内部点");
},
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
],
),
);
}
}
3、Widget的数据传递 event_bus
可以考虑使用 事件总线 https://pub.dev/packages/event_bus
比如现在有个需求
- 有两个Widget 一个是Button 、一个是Text
- 点击按钮的时候 显示数据内容
3.1 event_bus使用模型数据传递
import 'package:flutter/material.dart'; // runApp在这个material库里面
import 'package:event_bus/event_bus.dart';
// 1. 创建全局的EventBus对象
final eventBus = EventBus();
class eventBusUserInfo {
String nickname = "";
int level = 0;
eventBusUserInfo(this.nickname,this.level);
}
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: YHiOSHomePage(),
);
}
}
class YHiOSHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("手势模板_Widget"),
),
body: EventBusDemoWidget(),
);
}
}
class EventBusDemoWidget extends StatelessWidget {
const EventBusDemoWidget({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
YHButton(),
YHText(),
],
),
);
}
}
class YHButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(onPressed: (){
// 2.发布事件
// eventBus.fire("宇夜iOS");
final info = eventBusUserInfo("宇夜iOS", 100);
eventBus.fire(info);
},
child: Text("按钮"),
);
}
}
class YHText extends StatefulWidget {
const YHText({Key? key}) : super(key: key);
@override
State<YHText> createState() => _YHTextState();
}
class _YHTextState extends State<YHText> {
String _message = "Hello world";
@override
void initState() {
super.initState();
// 监听事件
eventBus.on<eventBusUserInfo>().listen((data) {
print(data.nickname);
print(data.level);
// 更新数据
setState(() {
_message = "${data.nickname} - ${data.level}";
});
});
}
@override
Widget build(BuildContext context) {
return Text(_message,style: TextStyle(fontSize: 20),);
}
}
3.1 效果图 - event_bus使用模型数据传递

- 创建全局的EventBus对象
final eventBus = EventBus();- 发布事件
eventBus.fire(“宇夜iOS”);- 监听事件
eventBus.on().listen((data) {
print(data.nickname);
print(data.level);
// 更新数据
setState(() {
_message = “${data.nickname} - ${data.level}”;
});
});
②、路由
还记得我们之前IndexStack我们做的豆瓣案例的页面切换
但是我们比如在首页 进入 首页详情页面。这种跳转来跳转去 一般是用Navigator来使用的 而Navigatorj就是路由
在Flutter中。路由管理主要有另两个类: Route和Navigator
1. Navigator
我们之前使用
material风格。其实是包含Navigator的、
所以我们开发的Navigator不需要创建的
1.1 Navigator的push和pop 以及传递参数 以及反向回传参数
传递参数 需要在第二页面里面声明变量存储起来
返回传递参数
main.dart
import 'package:flutter/material.dart';
import 'package:learn_flutter/day11_%E4%BA%8B%E4%BB%B6/details.dart'; // runApp在这个material库里面
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: YHiOSHomePage(),
);
}
}
class YHiOSHomePage extends StatefulWidget {
@override
State<YHiOSHomePage> createState() => _YHiOSHomePageState();
}
class _YHiOSHomePageState extends State<YHiOSHomePage> {
String _homeMessage = "";
@override
Widget build(BuildContext context) {
// Navigator.of(context).push(route)
return Scaffold(
appBar: AppBar(
title: Text("router模板_Widget"),
),
body: Center(
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_homeMessage,style: TextStyle(fontSize: 20),),
RaisedButton(
child: Text("跳转到详情"),
onPressed: () => _jumpToDetails(context),
),
],
),
),
);
}
void _jumpToDetails(BuildContext context){
// Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
// // 1.普通跳转方式
// // 传递参数 : 通过构造器直接传递
// return YHDetailsScreent("a home message");
// }));
// Navigator.push(context, route)
// 2. 接受详情页面的数据
Future result = Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
// 1.正向传递参数
return YHDetailsScreent("a home message");
}));
result.then((res) {
print(res);
setState(() {
_homeMessage = res;
});
});
}
}
1.2 反向传值方式1 重写导航的返回按钮
重写导航的返回按钮
appBar: AppBar(
title: Text(“详情页”),
// 自定义导航栏的返回按钮 并且监听返回的事件处理 回传参数
leading: IconButton(
icon: Icon(Icons.backspace),
onPressed: () => _backToHome(context),
),
)
import 'package:flutter/material.dart';
// 详情页面
class YHDetailsScreent extends StatelessWidget {
final String _message;
// const YHDetailsScreent({Key? key}) : super(key: key);
YHDetailsScreent(this._message);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("详情页"),
// 自定义导航栏的返回按钮 并且监听返回的事件处理 回传参数
leading: IconButton(
icon: Icon(Icons.backspace),
onPressed: () => _backToHome(context),
),
),
body: Center(
child: Column(
children: [
Text(_message,style: TextStyle(fontSize: 20),),
RaisedButton(child: Text("回到首页"), onPressed: () => _backToHome(context)
),
],
),
),
);
}
void _backToHome(BuildContext context){
print("回到首页");
Navigator.of(context).pop("a details message");
}
}
1.2 反向传值方式2 WillPopScope
import 'package:flutter/material.dart';
// 详情页面
class YHDetailsScreent extends StatelessWidget {
final String _message;
// const YHDetailsScreent({Key? key}) : super(key: key);
YHDetailsScreent(this._message);
@override
Widget build(BuildContext context) {
// 反向传值 方式2 使用 WillPopScope
return WillPopScope(
onWillPop: (){
print("反向传值 方式2 使用 WillPopScope");
_backToHome(context);
return Future.value(false);
},
child: Scaffold(
appBar: AppBar(
title: Text("详情页"),
// 反向传值 方式1 重写导航返回按钮的事件
// 自定义导航栏的返回按钮 并且监听返回的事件处理 回传参数
// leading: IconButton(
// icon: Icon(Icons.backspace),
// onPressed: () => _backToHome(context),
// ),
),
body: Center(
child: Column(
children: [
Text(_message,style: TextStyle(fontSize: 20),),
RaisedButton(child: Text("回到首页"), onPressed: () => _backToHome(context)
),
],
),
),
),
);
}
void _backToHome(BuildContext context){
print("回到首页");
Navigator.of(context).pop("a details message");
}
}
1.2 效果图 - 反向传值方式2 WillPopScope

2. 路由映射
如果开发过程中,我们跳转的详情代码 很长。
此时 我们可以使用路由映射。
也就是相当于给跳转页面 起别名的意思。
- 给页面命名
- 在MyApp设置路由
2.1 添加多一个关于页面作为演示路由映射
main.dart
import 'package:flutter/material.dart';
import 'package:learn_flutter/day11_%E4%BA%8B%E4%BB%B6/about.dart';
import 'package:learn_flutter/day11_%E4%BA%8B%E4%BB%B6/details.dart'; // runApp在这个material库里面
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// home: YHiOSHomePage(), // 如果有 路由并且设置initialRoute 那么home不用设置
routes: {
"/": (cxt) => YHiOSHomePage(),
"/about": (ctx) => YHAboutScreent(),
},
initialRoute: "/", // 初始化路由的页面为首页
);
}
}
class YHiOSHomePage extends StatefulWidget {
@override
State<YHiOSHomePage> createState() => _YHiOSHomePageState();
}
class _YHiOSHomePageState extends State<YHiOSHomePage> {
String _homeMessage = "";
@override
Widget build(BuildContext context) {
// Navigator.of(context).push(route)
return Scaffold(
appBar: AppBar(
title: Text("router模板_Widget"),
),
body: Center(
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_homeMessage,style: TextStyle(fontSize: 20),),
RaisedButton(
child: Text("跳转到详情"),
onPressed: () => _jumpToDetails(context),
),
RaisedButton(
child: Text("跳转到关于页"),
onPressed: () => _jumpToAbouts(context),
),
],
),
),
);
}
void _jumpToDetails(BuildContext context){
// Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
// // 1.普通跳转方式
// // 传递参数 : 通过构造器直接传递
// return YHDetailsScreent("a home message");
// }));
// Navigator.push(context, route)
// 2. 接受详情页面的数据
Future result = Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
// 1.正向传递参数
return YHDetailsScreent("a home message");
}));
result.then((res) {
print(res);
setState(() {
_homeMessage = res;
});
});
}
void _jumpToAbouts(BuildContext context){
// 跳转关于页
Navigator.of(context).pushNamed("/about");
}
}
about.dart
import 'package:flutter/material.dart';
class YHAboutScreent extends StatelessWidget {
const YHAboutScreent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("关于页"),
),
body: Column(
children: [
Text("11111"),
RaisedButton(
child: Text("返回首页"),
onPressed: (){
}),
],
),
);
}
}
2.1 效果图 - 添加多一个关于页面作为演示路由映射

2.3 ⭐️将路由映射的名字定义成常量、 将路由映射进行封装
定义成常量的好好处是 防止写错
规范: 定义在每个页面里面封装的好处: 利于开发管理
2.3.1 路由映射的名字定义成常量 - 以跳转到关于页面为例 并且获取参数
- 在About页面 声明变量
static const String routeName = “/about”;- 在MyApp的Route里面配置路由映射的名字
routes: {
YHiOSHomePage.routeName: (cxt) => YHiOSHomePage(),
YHAboutScreent.routeName: (ctx) => YHAboutScreent(),
},
initialRoute: YHiOSHomePage.routeName, // 初始化路由的页面为首页- 页面通过
pushNamed跳转时 并且传递参数。并且获取关于页面返回传递的参数final result = Navigator.of(context).pushNamed(YHAboutScreent.routeName,arguments: > "a > home message"); // 关于页面 返回获取数据 result.then((value) { print("about page pop value is ${value}"); });
获取传递过来的参数
final String message =ModalRoute.of(context)?.settings.argumentsas String;返回上一个页面并且传递参数
Navigator.of(context).pop("123");
2.3.2 命名路由跳转方式2- 钩子函数
不重构的情况下
不使用构造函数的方式进行跳转
2.3.2 命名路由跳转方式2- 钩子函数 - 以跳转详情页面为例子
我们在上面写了一个跳转详情页面的时候 使用的是构造函数进行跳转。
也就是说。我们每次跳转都需要传递一个message
Future result = Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
// 1.正向传递参数
return YHDetailsScreent(“a home message”);
}));
比如 我现在的需求 是不传递行不行
- 可以使用钩子函数
- 在MyApp里面配置
onGenerateRoute- 在
onGenerateRoute里面判断是哪个路由映射的名字 就处理创建哪个页面- 在
onUnknownRoute配置错误页面
main.dart
import 'package:flutter/material.dart';
import 'package:learn_flutter/day11_%E4%BA%8B%E4%BB%B6/about.dart';
import 'package:learn_flutter/day11_%E4%BA%8B%E4%BB%B6/details.dart'; // runApp在这个material库里面
import 'package:learn_flutter/day11_%E4%BA%8B%E4%BB%B6/unknown.dart'; // runApp在这个material库里面
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// home: YHiOSHomePage(), // 如果有 路由并且设置initialRoute 那么home不用设置
routes: {
YHiOSHomePage.routeName: (cxt) => YHiOSHomePage(),
YHAboutScreent.routeName: (ctx) => YHAboutScreent(),
},
// 钩子函数 - 能监听路由的名字
onGenerateRoute: (settings) {
if (settings.name == YHDetailsScreent.routeName) {
return MaterialPageRoute(
builder: (ctx) {
// 钩子函数 获取传递的参数
final String args = settings.arguments as String;
return YHDetailsScreent(args);
}
);
}
return null;
},
onUnknownRoute: (settings){
return MaterialPageRoute(builder: (ctx){
return YHUnknownScreent();
});
},
initialRoute: YHiOSHomePage.routeName, // 初始化路由的页面为首页
);
}
}
class YHiOSHomePage extends StatefulWidget {
static final String routeName = "/";
@override
State<YHiOSHomePage> createState() => _YHiOSHomePageState();
}
class _YHiOSHomePageState extends State<YHiOSHomePage> {
String _homeMessage = "";
@override
Widget build(BuildContext context) {
// Navigator.of(context).push(route)
return Scaffold(
appBar: AppBar(
title: Text("router模板_Widget"),
),
body: Center(
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_homeMessage,style: TextStyle(fontSize: 20),),
RaisedButton(
child: Text("跳转到详情"),
onPressed: () => _jumpToDetails(context),
),
RaisedButton(
child: Text("跳转到关于页"),
onPressed: () => _jumpToAbouts(context),
),
RaisedButton(
child: Text("跳转到详情2"),
onPressed: () => _jumpToDetails2(context),
),
RaisedButton(
child: Text("跳转到设置"),
onPressed: () => _jumpToSettings(context),
),
],
),
),
);
}
void _jumpToDetails(BuildContext context){
// Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
// // 1.普通跳转方式
// // 传递参数 : 通过构造器直接传递
// return YHDetailsScreent("a home message");
// }));
// Navigator.push(context, route)
// 2. 接受详情页面的数据
Future result = Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
// 1.正向传递参数
return YHDetailsScreent("a home message");
}));
result.then((res) {
print(res);
setState(() {
_homeMessage = res;
});
});
}
void _jumpToAbouts(BuildContext context){
// 跳转关于页
// pushNamed 传递参数 使用arguments
final result = Navigator.of(context).pushNamed(YHAboutScreent.routeName,arguments: "a home message");
// 关于页面 返回获取数据
result.then((value) {
print("about page pop value is ${value}");
});
}
void _jumpToDetails2(BuildContext context) {
final result = Navigator.of(context).pushNamed(YHDetailsScreent.routeName,arguments: "a details2 message");
result.then((value) {
print("details2 page pop value is ${value}");
});
}
void _jumpToSettings(BuildContext context) {
final result = Navigator.of(context).pushNamed("/settings");
}
}
details.dart
import 'package:flutter/material.dart';
// 详情页面
class YHDetailsScreent extends StatelessWidget {
static const String routeName = "/details";
final String _message;
// const YHDetailsScreent({Key? key}) : super(key: key);
YHDetailsScreent(this._message);
@override
Widget build(BuildContext context) {
// 反向传值 方式2 使用 WillPopScope
return WillPopScope(
onWillPop: (){
print("反向传值 方式2 使用 WillPopScope");
_backToHome(context);
return Future.value(false);
},
child: Scaffold(
appBar: AppBar(
title: Text("详情页"),
// 反向传值 方式1 重写导航返回按钮的事件
// 自定义导航栏的返回按钮 并且监听返回的事件处理 回传参数
// leading: IconButton(
// icon: Icon(Icons.backspace),
// onPressed: () => _backToHome(context),
// ),
),
body: Center(
child: Column(
children: [
Text(_message,style: TextStyle(fontSize: 20),),
RaisedButton(child: Text("回到首页"), onPressed: () => _backToHome(context)
),
],
),
),
),
);
}
void _backToHome(BuildContext context){
print("回到首页");
Navigator.of(context).pop("a details message");
}
}
unknown.dart
import 'package:flutter/material.dart';
class YHUnknownScreent extends StatelessWidget {
const YHUnknownScreent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("错误页面"),
),
body: Center(
child: Text("错误页面",style: TextStyle(fontSize: 20,color: Colors.red),),
),
);
}
}
2.3.2 效果图 - 命名路由跳转方式2- 钩子函数 - 以跳转详情页面为例子

2.3.3 将路由映射进行封装
从上面的代码看出 钩子函数 一个页面的处理很多
在开发过程中 我们一般情况是进行路由映射进行封装
方便管理
YHRoute.dart - 路由映射封装
import 'package:flutter/material.dart';
import 'package:learn_flutter/day09%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/03_globalKey%E7%9A%84%E4%BD%BF%E7%94%A8.dart';
import '../main.dart';
import '../about.dart';
import '../details.dart';
import '../unknown.dart';
class YHRoute {
// 路由映射
static final Map<String,WidgetBuilder> routes = {
YHiOSHomePage.routeName: (cxt) => YHiOSHomePage(),
YHAboutScreent.routeName: (ctx) => YHAboutScreent(),
};
// 首页初始化路由
static final String initialRoute = YHiOSHomePage.routeName;
// 钩子函数
static final RouteFactory generateRoute = (settings) {
if (settings.name == YHDetailsScreent.routeName) {
return MaterialPageRoute(
builder: (ctx) {
// 钩子函数 获取传递的参数
final String args = settings.arguments as String;
return YHDetailsScreent(args);
}
);
}
return null;
};
static final RouteFactory unknownRoute = (settings){
return MaterialPageRoute(builder: (ctx){
return YHUnknownScreent();
});
};
}
main.dart
路由封装的使用
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// home: YHiOSHomePage(), // 如果有 路由并且设置initialRoute 那么home不用设置
routes: YHRoute.routes,
// 钩子函数 - 能监听路由的名字
onGenerateRoute: YHRoute.generateRoute,
onUnknownRoute: YHRoute.unknownRoute,
initialRoute: YHRoute.initialRoute, // 初始化路由的页面为首页
);
}
}
本教程涵盖Flutter从环境搭建到实际项目开发全过程,包括Dart语言基础、Widget详解、事件监听及路由管理等内容,并通过豆瓣应用案例展示综合运用技巧。
1312

被折叠的 条评论
为什么被折叠?



