在特定页面上有没有办法停用Android后退按钮?
class WakeUpApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: "Time To Wake Up ?",
home: new WakeUpHome(),
routes: <String, WidgetBuilder>{
'/pageOne': (BuildContext context) => new pageOne(),
'/pageTwo': (BuildContext context) => new pageTwo(),
},
);
}
}
在页面上我有一个按钮转到pageTwo:
new FloatingActionButton(
onPressed: () {
Navigator.of(context).pushNamed('/pageTwo');
},
)
我的问题是如果我按下Android屏幕底部的后退箭头,我会回到pageOne。我希望这个按钮根本不显示。 理想情况下,除非用户将手指按在屏幕上5秒钟,否则我希望没有可能的方法离开此屏幕。 (我正在尝试为幼儿写一个应用程序,并希望只有父母能够导航出特定的屏幕)。
答案 0 :(得分:55)
答案是WillPopScope
。它将阻止页面被系统弹出。您仍然可以使用Navigator.of(context).pop()
@override
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: () async => false,
child: new Scaffold(
appBar: new AppBar(
title: new Text("data"),
leading: new IconButton(
icon: new Icon(Icons.ac_unit),
onPressed: () => Navigator.of(context).pop(),
),
),
),
);
}
答案 1 :(得分:3)
尽管Remi的答案是正确的,但通常您不想简单地阻止后退按钮,而是希望用户确认退出。
由于onWillPop
是未来,您可以通过从确认对话框中获得答案来类似地进行操作。
@override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(...),
onWillPop: () => showDialog<bool>(
context: context,
builder: (c) => AlertDialog(
title: Text('Warning'),
content: Text('Do you really want to exit'),
actions: [
FlatButton(
child: Text('Yes'),
onPressed: () => Navigator.pop(c, true),
),
FlatButton(
child: Text('No'),
onPressed: () => Navigator.pop(c, false),
),
],
),
),
);
}
答案 2 :(得分:2)
我在这里张贴这个,以防有人在那里找到这个并希望他们能找到一个简单的例子 https://gist.github.com/b-cancel/0ca372017a25f0c120b14dfca3591aa5
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(new BackButtonOverrideDemoWidget());
class BackButtonOverrideDemoWidget extends StatefulWidget{
@override
_BackButtonOverrideDemoWidgetState createState() => new _BackButtonOverrideDemoWidgetState();
}
class _BackButtonOverrideDemoWidgetState extends State<BackButtonOverrideDemoWidget> with WidgetsBindingObserver{
//-------------------------Test Variable
bool isBackButtonActivated = false;
//-------------------------Required For WidgetsBindingObserver
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
//-------------------------Function That Triggers when you hit the back key
@override
didPopRoute(){
bool override;
if(isBackButtonActivated)
override = false;
else
override = true;
return new Future<bool>.value(override);
}
//-------------------------Build Method
@override
Widget build(BuildContext context) {
return new Directionality(
textDirection: TextDirection.ltr,
child: new Container(
color: (isBackButtonActivated) ? Colors.green : Colors.red,
child: new Center(
child: new FlatButton(
color: Colors.white,
onPressed: () {
isBackButtonActivated = !isBackButtonActivated;
setState(() {});
},
child: (isBackButtonActivated) ?
new Text("DeActive the Back Button") : new Text("Activate the Back Button"),
)
)
),
);
}
}
答案 3 :(得分:2)
正如RémiRousselet所指出的,WillPopScope
通常是要走的路。但是,如果您开发的状态控件应直接对后退按钮做出反应,则可以使用以下方法:
答案 4 :(得分:2)
答案也许您知道使用 WillPopScope ,但是不幸的是,在 IOS 上,您不能 刷回 前一页,因此让我们自定义您的MaterialPageRoute:
class CustomMaterialPageRoute<T> extends MaterialPageRoute<T> {
@protected
bool get hasScopedWillPopCallback {
return false;
}
CustomMaterialPageRoute({
@required WidgetBuilder builder,
RouteSettings settings,
bool maintainState = true,
bool fullscreenDialog = false,
}) : super(
builder: builder,
settings: settings,
maintainState: maintainState,
fullscreenDialog: fullscreenDialog,
);
}
现在您可以使用WillPopScope,并且滑动以返回将在IOS上运行。详细答案在这里:https://github.com/flutter/flutter/issues/14203#issuecomment-540663717
答案 5 :(得分:1)
您可以使用Future.value(bool)
处理后退按钮。
bool _allow = true;
@override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(appBar: AppBar(title: Text("Back"))),
onWillPop: () {
return Future.value(_allow); // if true allow back else block it
},
);
}
答案 6 :(得分:1)
只需在应用栏的顶部添加一个容器即可隐藏后退按钮。
AppBar(
title: new Text('Page Title'),
leading: new Container(),
),
答案 7 :(得分:1)
如果您使用空安全编码,这里有一个替代解决方案。您需要禁用默认的后退按钮,并将其替换为 IconButton。在此示例中,当用户在退出前单击后退按钮进行确认时,我正在推送 AlertDialog。您可以替换此功能并将用户发送到任何其他页面
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
title: Text(),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => showDialog<bool>(
context: context,
builder: (c) => AlertDialog(
title: Text('Warning'),
content: Text('Are you sure you want to exit?'),
),
actions: [
TextButton(
child: Text('Yes'),
onPressed: () {
Navigator.pop(c, true);
Navigator.pop(context);
}),
TextButton(
child: Text('No'),
onPressed: () => Navigator.pop(c, false),
),
],
),
),
),
),
答案 8 :(得分:0)
您应该使用方法popAndPushNamed
而不是pushNamed
。它弹出当前路线并推动所需路线。
话虽如此,您的FAB代码应如下所示
new FloatingActionButton(
onPressed: () {
Navigator.popAndPushNamed(context, '/pageTwo');
},
)
答案 9 :(得分:0)
我使用mixin和WillPopScope小部件只是无法为我完成工作。
我发现这是最好的方法,比我认为的WillPopScope好得多。
final bool canPop = ModalRoute.of(context)?.canPop ?? false;
在应用栏内这样使用它:
leading: ModalRoute.of(context)?.canPop ?? false
? IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: (Platform.isAndroid)
? const Icon(Icons.arrow_back)
: const Icon(Icons.arrow_back_ios),
)
: Container(),
答案 10 :(得分:0)
尝试这个会杀死你的应用状态
@override
Widget build(BuildContext context) {
return WillPopScope(
////////////////
onWillPop: () => showDialog<bool>(
context: context,
builder: (c) => AlertDialog(
title: Text(
'Warning',
textAlign: TextAlign.center,
),
content: Text('Are you sure to exit?'),
actions: [
TextButton(
style: TextButton.styleFrom(
primary: Colors.green,
),
onPressed: () async {
exit(0);// kill app
},
child: Text('Yes'),
),
TextButton(
style: TextButton.styleFrom(
primary: Colors.red,
),
onPressed: () => Navigator.pop(c, false),
child: Text('No'),
)
],
),
),
/////////////////////
child: Scaffold(),
);
}
答案 11 :(得分:-2)
您可以使用的方法如下:
new FloatingActionButton(
onPressed: () {
Navigator.of(context).pushReplacementNamed('/pageTwo');
},
)
希望这会有所帮助。谢谢