有没有办法在特定页面上停用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(),
},
);
}
}
Run Code Online (Sandbox Code Playgroud)
在pageOne上我有一个按钮可以转到pageTwo:
new FloatingActionButton(
onPressed: () {
Navigator.of(context).pushNamed('/pageTwo');
},
)
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果我按下Android屏幕底部的后退箭头,我会回到pageOne.我希望这个按钮根本不显示.理想情况下,除非用户将手指按在屏幕上5秒钟,否则我希望没有可能的方法离开此屏幕.(我正在尝试为幼儿写一个应用程序,并希望只有父母能够导航出特定的屏幕).
Rém*_*let 95
答案是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(),
),
),
),
);
}
Run Code Online (Sandbox Code Playgroud)
Air*_*ark 35
虽然 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),
),
],
),
),
);
}
Run Code Online (Sandbox Code Playgroud)
Nhậ*_*rần 10
答案也许你知道那就是使用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,
);
}
Run Code Online (Sandbox Code Playgroud)
现在您可以使用 WillPopScope 并在 IOS 上滑动返回。详细答案在这里:https://github.com/flutter/flutter/issues/14203#issuecomment-540663717
小智 9
只是一个简单的方法。用 WillPopScope 小部件包裹脚手架。
WillPopScope(
onWillPop: () async => false,
child: Scaffold();
Run Code Online (Sandbox Code Playgroud)
您可以使用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
},
);
}
Run Code Online (Sandbox Code Playgroud)
我在这里发布这个以防有人发现这个并希望他们能找到一个简单的例子 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"),
)
)
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
正如RémiRousselet所指出的那样,WillPopScope通常是要走的路。但是,如果要开发一个有状态的小部件,该小部件应直接对后退按钮做出反应,则可以使用以下方法:
https://pub.dartlang.org/packages/back_button_interceptor
所选答案已过时
\nWillPopScope现已弃用,不应再使用。参考:Android 预测返回
\n\n为了支持 Android 14\xe2\x80\x99s Predictive Back 功能,一组提前 API 取代了即时导航 API,例如 WillPopScope 和 Navigator.willPop。
\n
如果您使用的是Flutter 3.14.0-7.0.pre或更高版本,则应将WillPopScopewidgets 替换为PopScope. 它有 2 个字段:
bool canPop, 启用/禁用系统后退手势(弹出);void Function(bool didPop)? onPopInvoked,是一个总是在系统返回手势时调用的回调,即使设置为 false,但在这种情况下,canPop路线不会弹出,并且didPop将设置为 false(因此您可以检查其值以区分逻辑)。回答你的问题:
\ncanPop: false;canPop: true(或使用某些逻辑条件或同步函数计算其值)并使用onPopInvoked: (bool didPop) {}.PopScope(\n canPop: _isSettingsChanged(),\n onPopInvoked: (bool didPop) async {\n if (didPop) {\n return;\n }\n final NavigatorState navigator = Navigator.of(context);\n final bool? shouldPop = await _showConfirmDialog("Unsaved settings. Discard?");\n if (shouldPop ?? false) {\n navigator.pop();\n }\n },\n child: child,\n)\nRun Code Online (Sandbox Code Playgroud)\n