Flutter 如何停用或覆盖安卓系统“;“后退”;按钮,在颤振?

Flutter 如何停用或覆盖安卓系统“;“后退”;按钮,在颤振?,flutter,Flutter,有没有办法在特定页面上禁用Android后退按钮 class WakeUpApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "Time To Wake Up ?", home: new WakeUpHome(), routes: <String, WidgetBuilder&

有没有办法在特定页面上禁用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(),
      },
    );
  }
}
我的问题是,如果我按下android屏幕底部的后退箭头,我会返回到第一页。我希望这个按钮根本不出现。
理想情况下,我希望没有可能的方法离开这个屏幕,除非用户将手指按在屏幕上5秒钟。(我正在尝试为学步儿童编写一个应用程序,希望只有家长能够导航出特定的屏幕)

答案是
WillPopScope
。它将防止系统弹出页面。您仍然可以使用
Navigator.of(context.pop()


我把这篇文章贴在这里,以防有人发现,并希望他们能找到一个简单的例子

导入“包装:颤振/材料.省道”;
导入“dart:async”;
void main()=>runApp(新的BackButtonOverrideDemoWidget());
类BackButtonOverridedeMowWidget扩展StatefulWidget{
@凌驾
_BackButtonOverrideDemoWidgetState createState()=>新建_BackButtonOverrideDemoWidgetState();
}
类_BackButtonOverrideDemoWidgetState使用WidgetsBindingObserver扩展状态{
//-------------------------测试变量
bool isBackButtonActivated=false;
//-------------------------WidgetsBindingObserver必需
@凌驾
void initState(){
super.initState();
WidgetsBinding.instance.addObserver(这个);
}
@凌驾
无效处置(){
WidgetsBinding.instance.removeObserver(此);
super.dispose();
}
//-------------------------按下后退键时触发的函数
@凌驾
didPopRoute(){
布尔覆盖;
如果(IsBackButton已激活)
覆盖=假;
其他的
覆盖=真;
返回新的Future.value(覆盖);
}
//-------------------------构建方法
@凌驾
小部件构建(构建上下文){
返回新方向性(
textDirection:textDirection.ltr,
子容器:新容器(
颜色:(isBackButtonActivated)?颜色。绿色:颜色。红色,
孩子:新中心(
孩子:新的扁平按钮(
颜色:颜色,白色,
已按下:(){
isBackButtonActivated=!isBackButtonActivated;
setState((){});
},
孩子:(BackButton是否已激活)?
新文本(“取消激活后退按钮”):新文本(“激活后退按钮”),
)
)
),
);
}
}

正如Rémi Rousselet指出的那样,
Willposcope
通常是一条路要走。但是,如果您正在开发一个有状态的小部件,它应该直接对后退按钮作出反应,那么您可以使用以下方法:


注意:我是这个软件包的作者。

您可以使用
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
    },
  );
}

虽然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),
          ),
        ],
      ),
    ),
  );
}
@覆盖
小部件构建(构建上下文){
返回式示波器(
儿童:脚手架(…),
onWillPop:()=>showDialog(
上下文:上下文,
生成器:(c)=>AlertDialog(
标题:文本(“警告”),
内容:文本(“您真的想退出吗”),
行动:[
扁平按钮(
子项:文本('Yes'),
onPressed:()=>Navigator.pop(c,true),
),
扁平按钮(
child:Text('No'),
onPressed:()=>Navigator.pop(c,false),
),
],
),
),
);
}

我使用了mixin和WillPopScope小部件,但无法为我完成这项工作。 这是我发现的最好的方法,在我看来比WillPopScope好得多。
final bool canPop=ModalRoute.of(上下文)?.canPop??虚假的
在appbar中这样使用它:

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(),

答案可能是您知道使用的是WillPopScope,但不幸的是,在IOS上,您无法刷回上一页,因此让我们自定义MaterialPage路线:

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,
        );
}
类CustomMaterialPageRoute扩展了MaterialPageRoute{
@保护
bool得到hasScopedWillPopCallback{
返回false;
}
CustomMaterialPage路线({
@必需的WidgetBuilder,
路由设置设置,
bool maintaintState=true,
bool fullscreenDialog=false,
}):超级(
建筑商:建筑商,
设置:设置,
maintaintState:maintaintState,
fullscreenDialog:fullscreenDialog,
);
}

现在你可以使用WillPopScope,向后滑动将在IOS上工作。详细答案如下:

如果您使用空安全性编码,这里有一个替代解决方案。您需要禁用默认的后退按钮,并将其替换为图标按钮。在本例中,当用户在退出前单击后退按钮确认时,我正在按下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),
              ),
            ],
          ),
        ),
      ),
    ),
返回WillPopScope(
onWillPop:()async=>false,
孩子:脚手架(
appBar:appBar(
自动嵌入:正确,
标题:Text(),
领先:IconButton(
图标:图标(图标。箭头返回),
onPressed:()=>showDialog(
上下文:上下文,
生成器:(c)=>AlertDialog(
标题:文本(“警告”),
内容:Text('您确定要退出吗?'),
),
行动:[
文本按钮(
子项:文本('Yes'),
已按下:(){
Navigator.pop(c,true);
Navigator.pop(上下文);
}),
文本按钮(
child:Text('No'),
onPressed:()=>Navigator.pop(c,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(),
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,
        );
}
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),
              ),
            ],
          ),
        ),
      ),
    ),