有没有办法检测用户是否离开了当前页面?我不认为WidgetsBinding会起作用,因为它会自己处理这些事件。那么,有人有什么解决办法吗?任何帮助都是感激的。
WidgetsBinding
wfypjpf41#
我有一个简单的解决方案,如果你说的“离开页面”是指用户从这个页面“返回”。如果你还想在用户打开当前页面之前的另一个页面时得到通知,下面的解决方案将不起作用。对于第一种情况,你可以使用WillPopScope,它是一个类,当包含的ModalRoute(由Navigator内部使用)将要弹出时,它会通知你,它甚至让你选择是否要弹出。只需将第二个屏幕的Scaffold Package 为WillPopScope。
ModalRoute
Navigator
Scaffold
WillPopScope
return WillPopScope( onWillPop: () async { // You can do some work here. // Returning true allows the pop to happen, returning false prevents it. return true; }, child: ... // Your Scaffold goes here. );
gmol16392#
根据你的描述,我认为你想跟踪你的用户,如果用户按下返回按钮或返回到上一个屏幕。您可以通过重写State类上的dispose来实现这一点。希望以下例子能帮助你找到解决方案。
State
dispose
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: EventRow(), ); } } class EventRow extends StatelessWidget { @override Widget build (BuildContext context) { return Scaffold( appBar: new AppBar( title: new Text("Demo"), ), body: Center( child: Container( child: new RaisedButton( onPressed: (){ Navigator.push( context, MaterialPageRoute(builder: (context) => SecondScreen()), ); }, child: Text("Goto Second Scrren"), ), ), ), ); } } class SecondScreen extends StatefulWidget { @override _SecondScreenState createState() => _SecondScreenState(); } class _SecondScreenState extends State<SecondScreen> { @override void initState() { // TODO: implement initState super.initState(); } @override void dispose() { // TODO: implement dispose print("Back To old Screen"); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: new Center( child: new Container( child: new RaisedButton( child: Text("Goto First Scrren"), onPressed: (){ Navigator.pop(context); } ), ), ), ); } }
83qze16e3#
如果您想检测用户是否离开屏幕,不管是返回(弹出)还是推送另一个上下文,RouteObserver和RouteAware都是一种方法。这里有一个例子,很抱歉它有点长,如果你试着运行它,你会发现它很简单。
import 'package:flutter/material.dart'; void main() async { runApp(App()); } class App extends StatelessWidget { static final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>(); @override Widget build(BuildContext context) { return MaterialApp( initialRoute: '/', navigatorObservers: [routeObserver], routes: { '/': (context) => Screen1(), 'screen2': (context) => Screen2(), }, ); } } class ScreenWrapper extends StatefulWidget { final Widget child; final Function() onLeaveScreen; final String routeName; ScreenWrapper({this.child, this.onLeaveScreen, @required this.routeName}); @override State<StatefulWidget> createState() { return ScreenWrapperState(); } } class ScreenWrapperState extends State<ScreenWrapper> with RouteAware { @override Widget build(BuildContext context) { return widget.child; } void onLeaveScreen() { if (widget.onLeaveScreen != null) { widget.onLeaveScreen(); } } @override void didChangeDependencies() { super.didChangeDependencies(); App.routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute); } @override void dispose() { super.dispose(); App.routeObserver.unsubscribe(this); } @override void didPush() { print('*** Entering screen: ${widget.routeName}'); } void didPushNext() { print('*** Leaving screen: ${widget.routeName}'); onLeaveScreen(); } @override void didPop() { print('*** Going back, leaving screen: ${widget.routeName}'); onLeaveScreen(); } @override void didPopNext() { print('*** Going back to screen: ${widget.routeName}'); } } class Screen1 extends StatelessWidget { @override Widget build(BuildContext context) { return ScreenWrapper( onLeaveScreen: () { print("***** Here's my special handling for leaving screen1!!"); }, routeName: '/', child: Scaffold( backgroundColor: Colors.yellow, body: SafeArea( child: Column( children: [ Text('This is Screen1'), FlatButton( child: Text('Press here to go to screen 2'), onPressed: () { Navigator.pushNamed(context, 'screen2'); }, ), FlatButton( child: Text( "Press here to go back (only works if you've pushed before)"), onPressed: () { Navigator.maybePop(context); }, ), ], ), ), ), ); } } class Screen2 extends StatelessWidget { @override Widget build(BuildContext context) { return ScreenWrapper( routeName: 'screen2', child: Scaffold( backgroundColor: Colors.blue, body: SafeArea( child: Column( children: [ Text('This is Screen2'), FlatButton( child: Text('Press here to go to screen 1'), onPressed: () { Navigator.pushNamed(context, '/'); }, ), FlatButton( child: Text( "Press here to go back (only works if you've pushed before)"), onPressed: () { Navigator.maybePop(context); }, ), ], ), ), ), ); } }
dsekswqp4#
您可以通过重写dispose()方法来实现这一点。
dispose()
vxf3dgd45#
我最近遇到了一个情况,我需要检测路线的变化,无论是弹出当前路线还是从当前路线推到新路线,我能够通过从答案here获得的RouteObserver实现这一点。使用WillPopScope,您可以在路由(pop)发生之前检测到可能的更改,并确定是否应该允许或拒绝它。如果您只是想在pop之后执行某个操作,可以通过重写onDispose来完成。
onDispose
u7up0aaq6#
对于Web部件,使用以下代码检测用户是否处于活动状态
if (kIsWeb) { EasyLoading.init(); window.addEventListener('focus', onFocus); window.addEventListener('blur', onBlur); } else { WidgetsBinding.instance.addObserver(this); }
6条答案
按热度按时间wfypjpf41#
我有一个简单的解决方案,如果你说的“离开页面”是指用户从这个页面“返回”。如果你还想在用户打开当前页面之前的另一个页面时得到通知,下面的解决方案将不起作用。
对于第一种情况,你可以使用WillPopScope,它是一个类,当包含的
ModalRoute
(由Navigator
内部使用)将要弹出时,它会通知你,它甚至让你选择是否要弹出。只需将第二个屏幕的
Scaffold
Package 为WillPopScope
。gmol16392#
根据你的描述,我认为你想跟踪你的用户,如果用户按下返回按钮或返回到上一个屏幕。
您可以通过重写
State
类上的dispose
来实现这一点。希望以下例子能帮助你找到解决方案。
83qze16e3#
如果您想检测用户是否离开屏幕,不管是返回(弹出)还是推送另一个上下文,RouteObserver和RouteAware都是一种方法。
这里有一个例子,很抱歉它有点长,如果你试着运行它,你会发现它很简单。
dsekswqp4#
您可以通过重写
dispose()
方法来实现这一点。vxf3dgd45#
我最近遇到了一个情况,我需要检测路线的变化,无论是弹出当前路线还是从当前路线推到新路线,我能够通过从答案here获得的RouteObserver实现这一点。
使用
WillPopScope
,您可以在路由(pop)发生之前检测到可能的更改,并确定是否应该允许或拒绝它。如果您只是想在pop之后执行某个操作,可以通过重写onDispose
来完成。u7up0aaq6#
对于Web部件,使用以下代码检测用户是否处于活动状态