我需要在用户通过按Android设备上的Back
按钮导航离开当前路线之前显示警告对话框。我试图通过在小部件状态中实现WidgetsBindingObserver
来拦截后退按钮行为。关于同一主题,GitHub上有一个关闭的issue。但是我的代码无效,因为从未调用过didPopRoute()方法。这是我的代码如下:
import 'dart:async';
import 'package:flutter/material.dart';
class NewEntry extends StatefulWidget {
NewEntry({Key key, this.title}) :super(key: key);
final String title;
@override
State<StatefulWidget> createState() => new _NewEntryState();
}
class _NewEntryState extends State<NewEntry> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Future<bool> didPopRoute() {
return showDialog(
context: context,
child: new AlertDialog(
title: new Text('Are you sure?'),
content: new Text('Unsaved data will be lost.'),
actions: <Widget>[
new FlatButton(
onPressed: () => Navigator.of(context).pop(true),
child: new Text('No'),
),
new FlatButton(
onPressed: () => Navigator.of(context).pop(false),
child: new Text('Yes'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.edit),
onPressed: () {},
),
);
}
}
答案 0 :(得分:14)
我发现解决方案是使用WillPopScope
小部件。以下是最终代码:
import 'dart:async';
import 'package:flutter/material.dart';
class NewEntry extends StatefulWidget {
NewEntry({Key key, this.title}) :super(key: key);
final String title;
@override
State<StatefulWidget> createState() => new _NewEntryState();
}
class _NewEntryState extends State<NewEntry> {
Future<bool> _onWillPop() {
return showDialog(
context: context,
child: new AlertDialog(
title: new Text('Are you sure?'),
content: new Text('Unsaved data will be lost.'),
actions: <Widget>[
new FlatButton(
onPressed: () => Navigator.of(context).pop(false),
child: new Text('No'),
),
new FlatButton(
onPressed: () => Navigator.of(context).pop(true),
child: new Text('Yes'),
),
],
),
) ?? false;
}
@override
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: _onWillPop,
child: new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.edit),
onPressed: () {},
),
),
);
}
}
答案 1 :(得分:0)
back_button_interceptor
软件包可以为您简化此过程,在更复杂的情况下尤其有用。
https://pub.dev/packages/back_button_interceptor#-readme-tab-
示例用法:
@override
void initState() {
super.initState();
BackButtonInterceptor.add(myInterceptor);
}
@override
void dispose() {
BackButtonInterceptor.remove(myInterceptor);
super.dispose();
}
bool myInterceptor(bool stopDefaultButtonEvent) {
print("BACK BUTTON!"); // Do some stuff.
return true;
}
答案 2 :(得分:0)
如果您使用的是GetX包,并且实现了GetMaterialApp
方法来初始化您的应用程序,则永远不会调用didPopRoute
中的didPushRoute
和WidgetsBindingObserver
方法。请改用routingCallback
,以下是示例,有关更多信息,请查看GetX documentation:
GetMaterialApp(
routingCallback: (routing) {
routing.isBack ? didPopRoute() : didPushRoute(routing.current);
}
)