【问题标题】:Flutter: Detect keyboard open and close [duplicate]Flutter:检测键盘打开和关闭[重复]
【发布时间】:2018-07-22 20:27:29
【问题描述】:

我的应用程序的最上层有一个BottomNavigationBar。我想检测应用程序/子树中基本上任何地方的键盘打开和关闭,所以只要键盘可见,我就可以显示和隐藏BottomNavigationBar

这是一个普遍问题,可能与BottomNavigationBar 没有直接关系。换句话说,从BottomNavigationBar 中抽象出来:-)

【问题讨论】:

标签: dart flutter


【解决方案1】:

要检查键盘可见性,只需检查小部件树中任意位置的viewInsets 属性。 viewInsets.bottom 等于 0 时键盘隐藏。

您可以使用MediaQuery 来检查viewInsets,例如:

MediaQuery.of(context).viewInsets.bottom

【讨论】:

  • 这是一种不好的做法。 ViewInset 并非特定于键盘。我建议使用 platform_channel 直接调用原生 API 来判断键盘是否可见。
  • @Darky 但这是你能做到的唯一方法。观察窗口大小以推断键盘是否可见,据我所知,没有直接的方法。你可以看看this。如果我错了,请纠正我。
  • 但 ViewInset 不是“isKeyboardVisible”。如果你有一个浮动键盘,它会在 ViewInset 为 0 时可见
  • 没错,但理想情况下isKeyboardVisible = viewInsets.bottom > 200px 或理想情况下不等于零。没有其他方法可以判断键盘是否可见。
  • 实现 WidgetsBindingObserver 尤其是方法 didChangeMetrics 可能是一个解决方案。见article
【解决方案2】:

我刚刚创建了一个 Flutter 插件来通知键盘打开和关闭事件。它适用于 Android 和 iOS。

keyboard_visibility


import 'package:keyboard_visibility/keyboard_visibility.dart';

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

  KeyboardVisibilityNotification().addNewListener(
    onChange: (bool visible) {
      print(visible);
    },
  );
}

【讨论】:

  • 我们应该如何使用这个插件?有什么文件吗?
  • 请参考自述。使用起来非常简单:link
  • 抱歉,我在 pub.dartlang 上找不到包。这太棒了,我发现这是知道键盘是否真的可见的唯一方法(即使您的键盘有浮动键盘)
  • 插件未更新,请转至此分支:github.com/MisterJimson/flutter_keyboard_visibility
  • 这个包不支持NULL SEFETY,所以它是无用的。
【解决方案3】:

您可以使用 keyboard_visibility 包来有效地执行此操作。我用过它,它就像一个魅力。

安装

dependencies:
  keyboard_visibility: ^0.5.2

用法

import 'package:keyboard_visibility/keyboard_visibility.dart';

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

  KeyboardVisibilityNotification().addNewListener(
    onChange: (bool visible) {
      print(visible);
    },
  );
}

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

Here is the link.

【讨论】:

  • 您的示例应该更清晰,并显示保存订阅 ID,并附带删除调用,否则如果您多次使用屏幕,您将获得多个侦听器。当类超出范围时,侦听器不会自动处理。除此之外,漂亮,干净,易于使用。谢谢!
  • 这个插件会阻止你为发布而构建
  • 我实际使用过它,我已经为发布而构建,甚至多次发布。
  • 此软件包不支持 NULL SAFETY。这现在没用了。
【解决方案4】:

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

    if(WidgetsBinding.instance.window.viewInsets.bottom > 0.0)
    {
       // Keyboard is visible.
    }
    else
    {
       // Keyboard is not visible.
    }

【讨论】:

  • 即使键盘处于活动状态或打开状态,它也会返回 0.0
  • (这真的是预期的语法突出显示吗?看起来很奇怪。可能是“窗口”匹配完全不同的东西(使用不同的编程语言)。)
【解决方案5】:

在您的StatefullWidget 中,创建一个变量:

bool _keyboardVisible = false;

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

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

【讨论】:

    【解决方案6】:

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

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

    【讨论】:

      【解决方案7】:

      你可以使用 Flutter keyboard visibility plugin

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

      【讨论】:

        【解决方案8】:

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

        /// My widget state,it can remove the focus to end editing when the keyboard is hidden.
        class MyWidgetState extends State<MyWidget> with WidgetsBindingObserver {
          /// Determine whether the keyboard is hidden.
          Future<bool> get keyboardHidden async {
            // If the embedded value at the bottom of the window is not greater than 0, the keyboard is not displayed.
            final check = () => (WidgetsBinding.instance?.window.viewInsets.bottom ?? 0) <= 0;
            // If the keyboard is displayed, return the result directly.
            if (!check()) return false;
            // 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.
            return await Future.delayed(Duration(milliseconds: 100), () => check());
          }
        
          @override
          void initState() {
            super.initState();
            // Used to obtain the change of the window size to determine whether the keyboard is hidden.
            WidgetsBinding.instance?.addObserver(this);
          }
        
          @override
          void dispose() {
            // stop Observing the window size changes.
            WidgetsBinding.instance?.removeObserver(this);
            super.dispose();
          }
          
          @override
          void didChangeMetrics() {
            // When the window insets changes, the method will be called by the system, where we can judge whether the keyboard is hidden.
            // If the keyboard is hidden, unfocus to end editing.
            keyboardHidden.then((value) => value ? FocusManager.instance.primaryFocus?.unfocus() : null);
          }
        }
        

        【讨论】:

          【解决方案9】:

          使用 Flutter 2.0 和 null 安全性,我使用这个包 - 它没有流,纯 Dart,提供有关键盘高度等的附加信息。

          flutter_keyboard_size 1.0.0+4

          【讨论】:

          • MediaQuery.of(context).viewInsets.bottom 已经给你键盘高度了吗?
          【解决方案10】:

          我在这里找到了一个更简单的解决方案:

          将DesiredBottomWidget放在Stack()Positioned(top: somevalue)中,出现键盘时会隐藏。

          例子:

          Stack(
              "Somewidget()",
              Positioned(
                  top: "somevalue",
                  child: "DesiredBottomWidget()"),
          ),
          

          【讨论】:

            【解决方案11】:

            我使用了一种解决方法。我在输入中添加了一个 focusNode 并为其添加了一个侦听器。

            在此处查看实现add focus listener to input

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-12-05
              • 1970-01-01
              • 1970-01-01
              • 2019-01-07
              • 1970-01-01
              • 2021-03-29
              • 2016-02-20
              • 1970-01-01
              相关资源
              最近更新 更多