Flutter WillPopScope用于嵌套导航 [英] Flutter WillPopScope for nested Navigation
问题描述
我有带有嵌套导航器的Flutter应用,并且我想覆盖"onBackPressed"在我的嵌套屏幕中使用WillPopScope
.
I have Flutter App with nested Navigator and I want to override "onBackPressed" using WillPopScope
in my nested screen.
假设我有MainScreen
,PrimaryScreen
和SecondaryScreen
.
PrimaryScreen
是嵌套的导航器,它具有多个屏幕,如PrimaryOneScreen
,PrimaryTwoScreen
和PrimaryThreeScreen
.
Let's say I have MainScreen
, PrimaryScreen
, and SecondaryScreen
.
PrimaryScreen
is nested Navigator, it have several screen like PrimaryOneScreen
, PrimaryTwoScreen
, and PrimaryThreeScreen
.
SecondaryScreen
也是嵌套导航器,就像PrimaryScreen
一样,它具有3个屏幕.
SecondaryScreen
is also a nested Navigator, just like PrimaryScreen
, it have 3 screens.
以下是我要实现的目标的说明
Here the illustration of what i want to achieve
MainScreen
-> PrimaryScreen
(PrimaryOneScreen
-> PrimaryTwoScreen
-> PrimaryThreeScreen
)
MainScreen
-> PrimaryScreen
(PrimaryOneScreen
-> PrimaryTwoScreen
-> PrimaryThreeScreen
)
当我在PrimaryTwoScreen
上的职位时,我想使用覆盖"onBackPressed"的位置回到PrimaryOneScreen
.使用WillPopScope
小部件.但是onWillPop
当我按下后退"按钮时从未调用,并且屏幕直接返回到MainScreen
.
When my position on PrimaryTwoScreen
, I want to get back to PrimaryOneScreen
with overriding "onBackPressed" using WillPopScope
Widget. But onWillPop
never called when I press back button, and my screen go back directly to MainScreen
.
这是我的密码
MainScreen.dart
MainScreen.dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MainApp(),
onGenerateRoute: (settings){
WidgetBuilder builder;
switch(settings.name){
case 'primary' :
builder = (BuildContext _) => PrimaryScreen();
break;
case 'secondary' :
builder = (BuildContext _) => SecondaryScreen();
break;
case 'main' :
builder = (BuildContext _) => MainApp();
break;
default :
throw Exception('Invalid route: ${settings.name}');
}
return MaterialPageRoute(
builder: builder,
settings: settings
);
},
);
}
}
class MainApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary');
},
child: Text('To Page Primary'),
),
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'secondary');
},
child: Text('To Page Secondary'),
)
],
),
);
}
}
PrimaryScreen.dart
PrimaryScreen.dart
class PrimaryScreen extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Navigator(
initialRoute: 'primary/pageone',
onGenerateRoute: (RouteSettings settings){
WidgetBuilder builder;
switch(settings.name){
case 'primary/pageone' :
builder = (BuildContext _) => PrimaryOneScreen();
break;
case 'primary/pagetwo' :
builder = (BuildContext _) => PrimaryTwoScreen();
break;
case 'primary/pagethree' :
builder = (BuildContext _) => PrimaryThreeScreen();
break;
default :
throw Exception('Invalid route: ${settings.name}');
}
return MaterialPageRoute(
builder: builder,
settings: settings
);
},
);
}
}
PrimaryOneScreen.dart
PrimaryOneScreen.dart
class PrimaryOneScreen extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Primary Page'),
),
body: Center(
child: Column(
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pagetwo');
},
child: Text('To Page Two'),
),
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pagethree');
},
child: Text('To Page Three'),
),
],
),
),
);
}
}
PrimaryTwoScreen.dart
PrimaryTwoScreen.dart
class PrimaryTwoScreen extends StatelessWidget{
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: ()async{
print('willPopScope');
Navigator.of(context, rootNavigator: false).pop();
return true;
},
child: Scaffold(
appBar: AppBar(
title: Text('Secondary Page'),
),
body: Center(
child: Column(
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pageone');
},
child: Text('To Page One'),
),
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pagethree');
},
child: Text('To Page Three'),
),
],
),
),
),
);
}
}
PrimaryThreeScreen.dart
PrimaryThreeScreen.dart
class PrimaryThreeScreen extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Primary Page'),
),
body: Center(
child: Column(
children: <Widget>[
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pageone');
},
child: Text('To Page One'),
),
FlatButton(
onPressed: (){
Navigator.pushNamed(context, 'primary/pagetwo');
},
child: Text('To Page Two'),
)
],
),
),
);
}
}
编辑 我添加了一张图像来说明我想要实现的目标.
EDIT I added an image to illustrate what I want to achieve.
如何仅在嵌套导航器上弹出?
How to pop only on nested navigator?
谢谢!
推荐答案
尝试使用此链接 https://medium.com/flutter-community/flutter-push-pop-push-1bb718b13c31
检查用例:pushReplacementNamed 标记说明
这篇关于Flutter WillPopScope用于嵌套导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!