颤动:检测键盘打开/关闭

Jak*_*sen 10 dart flutter

我有一个BottomNavigationBar在我的应用程序的最高级别.我想检测键盘打开/关闭基本上在app /子树的任何地方,所以我可以显示/隐藏BottomNavigationBar键盘可见.

这是一个普遍问题,可能与此无直接关系BottomNavigationBar.换句话说,摘自BottomNavigationBar:-)

And*_*eev 28

键盘可见性构建器

如果您不想依赖外部库,您可以使用WidgetsBindingObservermixin监听键盘显示/隐藏事件。我准备了一个轻量级的KeyboardVisibilityBuilder小部件来处理你的行为。用法非常类似于AnimatedBuilder

return KeyboardVisibilityBuilder(
  builder: (context, child, isKeyboardVisible) {
    if (isKeyboardVisible) {
      // build layout for visible keyboard
    } else {
      // build layout for invisible keyboard
    }
  },
  child: child, // this widget goes to the builder's child property. Made for better performance.
);
Run Code Online (Sandbox Code Playgroud)

KeyboardVisibilityBuilder 执行:

/// Calls `builder` on keyboard close/open.
/// https://stackoverflow.com/a/63241409/1321917
class KeyboardVisibilityBuilder extends StatefulWidget {
  final Widget? child;
  final Widget Function(
    BuildContext context,
    Widget? child,
    bool isKeyboardVisible,
  ) builder;

  const KeyboardVisibilityBuilder({
    Key? key,
    this.child,
    required this.builder,
  }) : super(key: key);

  @override
  _KeyboardVisibilityBuilderState createState() =>
      _KeyboardVisibilityBuilderState();
}

class _KeyboardVisibilityBuilderState extends State<KeyboardVisibilityBuilder>
    with WidgetsBindingObserver {
  var _isKeyboardVisible = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance!.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeMetrics() {
    final bottomInset = WidgetsBinding.instance!.window.viewInsets.bottom;
    final newValue = bottomInset > 0.0;
    if (newValue != _isKeyboardVisible) {
      setState(() {
        _isKeyboardVisible = newValue;
      });
    }
  }

  @override
  Widget build(BuildContext context) => widget.builder(
        context,
        widget.child,
        _isKeyboardVisible,
      );
}

Run Code Online (Sandbox Code Playgroud)


Abd*_*jao 20

您可以使用keyboard_visibility包来有效地执行此操作,我已经使用过它并且它的工作原理非常棒。

安装

dependencies:
  keyboard_visibility: ^0.5.2
Run Code Online (Sandbox Code Playgroud)

用法

import 'package:keyboard_visibility/keyboard_visibility.dart';

@protected
void initState() {
  super.initState();

  KeyboardVisibilityNotification().addNewListener(
    onChange: (bool visible) {
      print(visible);
    },
  );
}
Run Code Online (Sandbox Code Playgroud)

它还支持显示/隐藏等侦听器。

链接在这里

  • 用这个。https://pub.dev/packages/flutter_keyboard_visibility (4认同)
  • 该插件将阻止您进行构建发布 (2认同)

Hem*_*Raj 14

要检查键盘可见性,只需检查viewInsets窗口小部件树中任何位置的属性.键盘viewInsets.bottom在等于零时隐藏.

您可以检查viewInsetsMediaQuery这样的:

MediaQuery.of(context).viewInsets.bottom
Run Code Online (Sandbox Code Playgroud)

希望有所帮助!

  • 但 ViewInset 不是“isKeyboardVisible”。例如,如果您有一个浮动键盘,它将在 ViewInset 为 0 时可见 (5认同)
  • 这是一个不好的做法.ViewInset不是特定于键盘.我建议使用platform_channel直接调用本机API,告诉键盘是否可见. (4认同)
  • 实现 **WidgetsBindingObserver** 尤其是方法 *didChangeMetrics* 可能是一个解决方案。见[文章](https://www.didierboelens.com/2018/04/hint-4-ensure-a-textfield-or-textformfield-is-visible-in-the-viewport-when-has-the-focus /) (2认同)
  • 在大多数情况下,当有浮动键盘时,您无论如何都会将其视为无键盘!比如qn中给出的例子...带有底部栏...为什么当浮动键盘出现时要隐藏底部栏?!‍♀️(不过,我猜,您可能仍然想知道一些用例。但它们一定很少!) (2认同)

小智 13

我刚刚创建了一个flutter插件来通知键盘打开/关闭事件.适用于Android和iOS.希望这可以帮助

https://github.com/adee42/flutter_keyboard_visibility

  • 这个包不支持 NULL SEFETY,这就是它没用的原因。 (5认同)
  • 插件未更新,请转至此分支:https://github.com/MisterJimson/flutter_keyboard_visibility (2认同)

jqg*_*imo 12

这是我的解决方案,使用WidgetsBindingObserver来观察窗口大小变化,并据此判断键盘是否隐藏。

\n
/// My widget state\xef\xbc\x8cit can remove the focus to end editing when the keyboard is hidden.\nclass MyWidgetState extends State<MyWidget> with WidgetsBindingObserver {\n  /// Determine whether the keyboard is hidden.\n  Future<bool> get keyboardHidden async {\n    // If the embedded value at the bottom of the window is not greater than 0, the keyboard is not displayed.\n    final check = () => (WidgetsBinding.instance?.window.viewInsets.bottom ?? 0) <= 0;\n    // If the keyboard is displayed, return the result directly.\n    if (!check()) return false;\n    // If the keyboard is hidden, in order to cope with the misjudgment caused by the keyboard display/hidden animation process, wait for 0.1 seconds and then check again and return the result.\n    return await Future.delayed(Duration(milliseconds: 100), () => check());\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    // Used to obtain the change of the window size to determine whether the keyboard is hidden.\n    WidgetsBinding.instance?.addObserver(this);\n  }\n\n  @override\n  void dispose() {\n    // stop Observing the window size changes.\n    WidgetsBinding.instance?.removeObserver(this);\n    super.dispose();\n  }\n  \n  @override\n  void didChangeMetrics() {\n    // When the window insets changes, the method will be called by the system, where we can judge whether the keyboard is hidden.\n    // If the keyboard is hidden, unfocus to end editing.\n    keyboardHidden.then((value) => value ? FocusManager.instance.primaryFocus?.unfocus() : null);\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n


dee*_*raj 10

您可以使用WidgetsBinding.instance.window.viewInsets.bottom,如果它的值大于0.0然后键盘是可见的。

    if(WidgetsBinding.instance.window.viewInsets.bottom > 0.0)
    {
       //Keyboard is visible.
    }
    else
    {
       //Keyboard is not visible.
    }
Run Code Online (Sandbox Code Playgroud)

  • 即使键盘处于活动状态或打开状态,它也会返回 0.0 (4认同)

Abd*_*pal 8

在你StatefullWidget创建一个变量

bool _keyboardVisible = false;
Run Code Online (Sandbox Code Playgroud)

然后在build小部件上初始化该变量;

@override
Widget build(BuildContext context) {
    _keyboardVisible = MediaQuery.of(context).viewInsets.bottom != 0;
   return child;
}
Run Code Online (Sandbox Code Playgroud)


小智 8

您可以使用 Flutter 键盘可见性插件

@override
Widget build(BuildContext context) {
  return KeyboardVisibilityBuilder(
    builder: (context, isKeyboardVisible) {
      return Text(
        'The keyboard is: ${isKeyboardVisible ? 'VISIBLE' : 'NOT VISIBLE'}',
      );
    }
  );
Run Code Online (Sandbox Code Playgroud)

  • 最干净的解决方案!谢谢 (2认同)

小智 6

您可以使用MediaQuery.of(context).viewInsets.bottom. 只需查看下面的文档。

/// 被系统 UI 完全遮挡的显示部分, /// 通常被设备的键盘遮挡。/// /// 当移动设备的键盘可见时viewInsets.bottom /// 对应于键盘的顶部。/// /// 该值与 [padding] 无关:这两个值都是 /// 从 [MediaQuery] 小部件边界的边缘测量的。/// 由 [WidgetsApp] 创建的顶级 MediaQuery 的边界与包含应用程序的窗口(通常是移动设备屏幕)相同。///
/// 另请参阅: /// /// * [MediaQueryData],它提供了有关此 /// 属性的一些其他详细信息以及它与 [padding] 的区别。最终的 EdgeInsets viewInsets;