有什么方法可以检测用户是否离开当前页面?我认为这WidgetsBinding不会起作用,因为它可以自行处理这些事件。那么,有人有什么解决方案吗?任何帮助表示赞赏。
Mar*_*cel 14
如果“离开页面”是指用户从该页面“返回”,我有一个简单的解决方案。如果您还想在用户打开当前页面之前的另一个页面时收到通知,则以下解决方案将不起作用。
对于第一种情况,您可以使用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.
);
Run Code Online (Sandbox Code Playgroud)
Vir*_*iya 11
根据您的描述,我认为您想在用户按下后退按钮或返回上一屏幕时跟踪您的用户。
您可以通过覆盖类dispose上的来实现这一点State。
可以以下示例帮助您找出解决方案。
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);
}
),
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
RouteObserver 和 RouteAware 如果您想检测用户是否离开屏幕,无论是返回(弹出)还是推送另一个上下文,都可以使用 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));
}
@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);
},
),
],
),
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1584 次 |
| 最近记录: |