Flutter iOS向后滑动不调用WillPop

nzk0hqpo  于 2023-03-09  发布在  Flutter
关注(0)|答案(5)|浏览(554)

我用WillPopScope覆盖了我的Scaffold,但是当滑动返回iOS时,onWillPop回调没有被调用。
这可能是什么原因呢?

@override
Widget build(BuildContext context) {
  return WillPopScope(
    onWillPop: () async {
      print("onWillPop"); // is not printed to the console
      if (Navigator.of(context).userGestureInProgress)
        return false;
      else
        return true;
    },
    child: new Scaffold(
      appBar: new AppBar(
        title: new Text("App Title"),
      ),
      body: Stack(
        children: <Widget>[
          ...widgets...
        ],
      ),
    ),
  );
}
olmpazwi

olmpazwi1#

正如这里提到的,要使您的WillPopScope工作,您应该覆盖MaterialPageRoute中的hasScopedWillPopCallbackgetter,如下所示:

class CustomMaterialPageRoute extends MaterialPageRoute {
  @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。它肯定会使WillPopScope同时适用于IOS和Android平台。

8wtpewkr

8wtpewkr2#

我找到了原因:WillPopScope不起作用是因为上面构建方法的小部件不是top小部件(main调用的小部件),希望对其他人有所帮助。

rkttyhzu

rkttyhzu3#

像这样的小工具很有效。

import 'package:flutter/cupertino.dart';
import 'dart:io' show Platform;

class CustomWillPopScope extends StatelessWidget {

  const CustomWillPopScope({required this.child, this.onWillPop = false, Key? key, required this.action}) : super(key: key);

  final Widget child;
  final bool onWillPop;
  final VoidCallback action;

  @override
  Widget build(BuildContext context) {
    return Platform.isIOS ?
    GestureDetector(
        onPanEnd: (details) {
          if (details.velocity.pixelsPerSecond.dx < 0 || details.velocity.pixelsPerSecond.dx > 0) {
            if(onWillPop){
              action();
            }
          }
        },
        child: WillPopScope(
          onWillPop: ()async{
            return false;
          },
          child: child,
        )
    )
        : WillPopScope(child: child, onWillPop: () async {
      action();
      return onWillPop;
    });
  }
}
rmbxnbpk

rmbxnbpk4#

将其作为顶层小部件,可能放在build函数中:

bool canNavigateBack = true;//This should come from a Stream/bloc/etc.

return WillPopScope(
        onWillPop: () {
          if (Platform.isAndroid) {
            if (canNavigateBack) {
              //Navigate back actions
            } else {
              //Show exit dialog, etc.
            }
          }
          return Future.value(false);
        },
        child: Platform.isIOS
            ? GestureDetector(
                onHorizontalDragEnd: (details) {
                  if (details.velocity.pixelsPerSecond.dx > 50) {
                    if (canNavigateBack) {
                      //Navigate back actions
                    } else {
                      //Show exit dialog, etc.
                    }
                  }
                },
                child: _anotherWidget())
            : _anotherWidget(),
      );
6tdlim6h

6tdlim6h5#

这是一个问题,在这个issue中讨论了很多,但是有一种方法可以修复它,那就是使用this package

return ConditionalWillPopScope(
child: _MyScreenContent(),
onWillPop: _onWillPop,
shouldAddCallbacks: _hasChanges,
 );

相关问题