如何在 Flutter 离开页面前显示确认对话框
How to show confirm dialog before leaving the page in Flutter
我有一个包含三个不同页面的应用程序。要在页面之间导航,我使用底部导航。其中一个页面包含一个表单。在离开表单页面之前,我想显示一个确认对话框。我知道我可以使用 WillPopScope 拦截设备的后退按钮。这非常有效。但是当我通过底部导航离开页面时,WillPopScope 并没有被触发。
我也尝试过使用 WidgetsBindingObserver,但是 didPopRoute 和 didPushRoute 都没有被触发。
有什么办法吗?
我的表单页面:
class TodayTimeRecordFormState extends State<TodayTimeRecordForm> with WidgetsBindingObserver{
final formKey = GlobalKey<FormState>();
TodayTimeRecordFormState();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Future<bool> didPopRoute() {
//never called
_onWillPop();
}
@override
Future<bool> didPushRoute(String route){
//never called
_onWillPop();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
// called when the device back button is pressed.
onWillPop: _onWillPop,
child: Scaffold(...));
}
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'),
),
],
),
);
}
}
包含底部导航的页面:
const List<Navigation> allNavigationItems = <Navigation>[
Navigation('Form', Icons.home, Colors.orange),
Navigation('Page2', Icons.work_off, Colors.orange),
Navigation('Page3', Icons.poll, Colors.orange)
];
class HomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return HomePageState();
}
}
class HomePageState extends State<HomePage> {
int selectedTab = 0;
final pageOptions = [
TodayTimeRecordForm(),
Page2(),
Page3(),
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(AppConfig.instance.values.title),
),
body: pageOptions[selectedTab],
bottomNavigationBar: BottomNavigationBar(
currentIndex: selectedTab,
unselectedItemColor: Colors.grey,
showUnselectedLabels: true,
selectedItemColor: Colors.amber[800],
onTap: (int index) {
setState(() {
selectedTab = index;
});
},
items: allNavigationItems.map((Navigation navigationItem) {
return BottomNavigationBarItem(
icon: Icon(navigationItem.icon),
backgroundColor: Colors.white,
label: navigationItem.title);
}).toList(),
),
);
}
}
您可以通过修改 BottomNavigationBar
的 onTap
来实现。
onTap: (int index) {
if (selectedTab == 0 && index != 0){
// If the current tab is the first tab (the form tab)
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.pop(context), // Closes the dialog
child: new Text('No'),
),
new FlatButton(
onPressed: () {
setState(()=>selectedTab = index); // Changes the tab
Navigator.pop(context); // Closes the dialog
},
child: new Text('Yes'),
),
],
),
);
} else {
// If the current tab isn't the form tab
setState(()=>selectedTab = index);
}
},
我有一个包含三个不同页面的应用程序。要在页面之间导航,我使用底部导航。其中一个页面包含一个表单。在离开表单页面之前,我想显示一个确认对话框。我知道我可以使用 WillPopScope 拦截设备的后退按钮。这非常有效。但是当我通过底部导航离开页面时,WillPopScope 并没有被触发。
我也尝试过使用 WidgetsBindingObserver,但是 didPopRoute 和 didPushRoute 都没有被触发。
有什么办法吗?
我的表单页面:
class TodayTimeRecordFormState extends State<TodayTimeRecordForm> with WidgetsBindingObserver{
final formKey = GlobalKey<FormState>();
TodayTimeRecordFormState();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Future<bool> didPopRoute() {
//never called
_onWillPop();
}
@override
Future<bool> didPushRoute(String route){
//never called
_onWillPop();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
// called when the device back button is pressed.
onWillPop: _onWillPop,
child: Scaffold(...));
}
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'),
),
],
),
);
}
}
包含底部导航的页面:
const List<Navigation> allNavigationItems = <Navigation>[
Navigation('Form', Icons.home, Colors.orange),
Navigation('Page2', Icons.work_off, Colors.orange),
Navigation('Page3', Icons.poll, Colors.orange)
];
class HomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return HomePageState();
}
}
class HomePageState extends State<HomePage> {
int selectedTab = 0;
final pageOptions = [
TodayTimeRecordForm(),
Page2(),
Page3(),
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(AppConfig.instance.values.title),
),
body: pageOptions[selectedTab],
bottomNavigationBar: BottomNavigationBar(
currentIndex: selectedTab,
unselectedItemColor: Colors.grey,
showUnselectedLabels: true,
selectedItemColor: Colors.amber[800],
onTap: (int index) {
setState(() {
selectedTab = index;
});
},
items: allNavigationItems.map((Navigation navigationItem) {
return BottomNavigationBarItem(
icon: Icon(navigationItem.icon),
backgroundColor: Colors.white,
label: navigationItem.title);
}).toList(),
),
);
}
}
您可以通过修改 BottomNavigationBar
的 onTap
来实现。
onTap: (int index) {
if (selectedTab == 0 && index != 0){
// If the current tab is the first tab (the form tab)
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.pop(context), // Closes the dialog
child: new Text('No'),
),
new FlatButton(
onPressed: () {
setState(()=>selectedTab = index); // Changes the tab
Navigator.pop(context); // Closes the dialog
},
child: new Text('Yes'),
),
],
),
);
} else {
// If the current tab isn't the form tab
setState(()=>selectedTab = index);
}
},