如何在 flutter 中检测页面转换是否完成?
背景:当我弹出一个页面时,我想在页面转换完成后启动一个功能。
当您
push
您的新路由也可以包含弹出路由中的数据时,您可以注册回调,例如,如果您需要从中传递数据。
Navigator.of(context).push(/*Some route*/).then((data) {
// You can call your function here. data will be null if nothing is passed from the popped route
});
如果你想从弹出的路线中通过
data
,就这样吧
Navigator.of(context).pop(someData);
如果你想知道转换实际上何时结束,你也可以为其注册一个回调监听器
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => RouteWidget())
..completed.then((_) {print('transition completed');},
),
);
如果您保留对路线的引用并使用 didPush() TickerFuture,也可以等待推送转换
MaterialPageRoute route = MaterialPageRoute(builder: (context) => MyPage());
Navigator.of(context).push(route);
await route.didPush(); // you could also use then instead of await
// ROUTE FINISHED TRANSITION HERE
如果您有多个堆叠导航器并且您希望它们之间的过渡更平滑,则可以使用此功能。就像等待导航器 1 完成推送后,再弹出当前活动的导航器 2 以显示导航器 1 的页面
等待动画在第二页完成(如果你想在动画转换后更新页面,这很有用)
第一页:
...
Navigator.push(
context,
PageRouteBuilder(
transitionDuration: Duration(milliseconds: 3000), //optional but useful for testing
pageBuilder: (_, animation, ___) => SecondPage(
pageBuilderAnimation: animation,
)));
...
第二页:
class SecondPage extends StatefulWidget {
const SecondPage ({Key? key, this.pageBuilderAnimation});
final Animation<double>? pageBuilderAnimation;
@override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
bool isTransitioning = true;
@override
void initState() {
super.initState();
if (widget.pageBuilderAnimation != null)
widget.pageBuilderAnimation!.addListener(() {
if (widget.pageBuilderAnimation!.isCompleted)
setState(() => isTransitioning = false);
});
else
isTransitioning = false;
}
...
}
如果您需要回调来完成推送和弹出动画,只需使用路由的 animation 附加状态侦听器。
短:
route.animation?.addStatusListener((AnimationStatus status) {
if (status.isCompleted) {
print('push animation finished');
} else if (status.isDismissed) {
print('pop animation finished');
}
});
完整代码:
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show timeDilation;
void main() {
timeDilation = 10.0; // slow down any animation
runApp(DemoApp());
}
class DemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
textTheme: const TextTheme(
bodyMedium: TextStyle(fontSize: 20),
),
elevatedButtonTheme: const ElevatedButtonThemeData(
style: ButtonStyle(
textStyle: WidgetStatePropertyAll(TextStyle(fontSize: 20)),
),
),
),
home: PageOne(),
);
}
}
class PageOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Page one'),
ElevatedButton(
child: const Text('Open page two'),
onPressed: () async {
print('--------- open tap ---------');
// 1. build route
final route = MaterialPageRoute(builder: (_) => PageTwo());
// 2. push route
final routeFuture = Navigator.of(context).push(route);
// 3. attach animation status listener
route.animation?.addStatusListener((AnimationStatus status) {
if (status.isCompleted) {
print('push animation finished');
} else if (status.isDismissed) {
print('pop animation finished');
}
});
// 4. If you awaiting something from page two
final result = await routeFuture;
print('result: $result');
},
)
],
),
),
);
}
}
class PageTwo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Page two'),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop('Some data from page two');
},
child: const Text('Return result'),
),
],
),
),
);
}
}