在 Flutter 应用程序中通过向后滑动手势关闭键盘

Dismiss keyboard on swipe back gesture in Flutter app

我试图在用户从边缘滑动到弹出路线时关闭键盘。

目前,键盘在路由完全弹出之前不会关闭,在关闭之前会扰乱其他一些页面布局

我确实尝试使用 WillPopScope 来确定用户何时要弹出路线,但不幸的是,这会禁用 iOS 或 CupertinoPageRoute 的滑动弹出功能.

我只是想知道是否无论如何我都可以确定用户何时从边缘滑动以弹出或点击 appBar 上的后退按钮并在他们这样做时关闭键盘。

如果可能的话,我会在键盘开始滑动弹出时尝试关闭键盘,这在许多应用程序中都会发生。

我正在附上一张 gif 图像,显示我正在努力实现的效果。

这应该是自然而然的,你不应该直接关心它,因为实际上,当你打开键盘弹出一个路由时,它应该正确关闭。

但是,如果您想检测用户何时开始滑动并关闭键盘,然后弹出当前路线,您可以通过用 GestureDetector 包装您的屏幕小部件来轻松实现它:

 Widget build(BuildContext context) {
    double dragStart = 0.0;
    return GestureDetector(
      onHorizontalDragStart: (details) => dragStart = details.globalPosition.dx,
      onHorizontalDragUpdate: (details) {
        final double screenWidth = MediaQuery.of(context).size.width;

        // Here I considered a back swipe only when the user swipes until half of the screen width, but you can tweak it to your needs.
        if (dragStart <= screenWidth * 0.05 && details.globalPosition.dx >= screenWidth) {
          FocusScope.of(context).unfocus();
        }
       child: // Your other widgets...
      },

您需要创建一个扩展 NavigatorObserver 的自定义 class,并将其实例传递给 MaterialApp 或 [的 navigatorObservers 属性 =13=].

在该自定义 class 中,您可以覆盖 didStartUserGesturedidStopUserGesture,滑动手势 starts/ends 时将调用它们。这应该允许您实现您正在寻找的行为。请注意,didStartUserGesture 表示当前路线以及之前的路线,您可以在此基础上添加逻辑来确定是否应关闭键盘。

根据 Ovidiu 的建议

class DismissKeyboardNavigationObserver extends NavigatorObserver {
  @override
  void didStartUserGesture(Route route, Route previousRoute) {
    SystemChannels.textInput.invokeMethod('TextInput.hide');
    super.didStartUserGesture(route, previousRoute);
  }
}

并在您的 Material 应用中

MaterialApp(
  navigatorObservers: [DismissKeyboardNavigationObserver()],
)

这是我为处理这个问题而写的东西。不使用任何外部包,您只需将您的内容包装在顶部的主要功能中。

Widget swipeOffKeyboard(BuildContext context, {Widget? child}) {
  return Listener(
    onPointerMove: (PointerMoveEvent pointer) {
      disKeyboard(pointer, context);
    },
    child: child, // your content should go here
  );
}

void disKeyboard(PointerMoveEvent pointer, BuildContext context) {
  double insets = MediaQuery.of(context).viewInsets.bottom;
  double screenHeight = MediaQuery.of(context).size.height;
  double position = pointer.position.dy;
  double keyboardHeight = screenHeight - insets;
  if (position > keyboardHeight && insets > 0) FocusManager.instance.primaryFocus?.unfocus();
}