【发布时间】:2018-07-22 20:27:29
【问题描述】:
我的应用程序的最上层有一个BottomNavigationBar。我想检测应用程序/子树中基本上任何地方的键盘打开和关闭,所以只要键盘可见,我就可以显示和隐藏BottomNavigationBar。
这是一个普遍问题,可能与BottomNavigationBar 没有直接关系。换句话说,从BottomNavigationBar 中抽象出来:-)
【问题讨论】:
我的应用程序的最上层有一个BottomNavigationBar。我想检测应用程序/子树中基本上任何地方的键盘打开和关闭,所以只要键盘可见,我就可以显示和隐藏BottomNavigationBar。
这是一个普遍问题,可能与BottomNavigationBar 没有直接关系。换句话说,从BottomNavigationBar 中抽象出来:-)
【问题讨论】:
要检查键盘可见性,只需检查小部件树中任意位置的viewInsets 属性。 viewInsets.bottom 等于 0 时键盘隐藏。
您可以使用MediaQuery 来检查viewInsets,例如:
MediaQuery.of(context).viewInsets.bottom
【讨论】:
isKeyboardVisible = viewInsets.bottom > 200px 或理想情况下不等于零。没有其他方法可以判断键盘是否可见。
我刚刚创建了一个 Flutter 插件来通知键盘打开和关闭事件。它适用于 Android 和 iOS。
import 'package:keyboard_visibility/keyboard_visibility.dart';
@override
void initState() {
super.initState();
KeyboardVisibilityNotification().addNewListener(
onChange: (bool visible) {
print(visible);
},
);
}
【讨论】:
您可以使用 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);
},
);
}
它还支持显示/隐藏等监听器。
【讨论】:
您可以使用WidgetsBinding.instance.window.viewInsets.bottom。如果它的值大于0.0,那么键盘是可见的。
if(WidgetsBinding.instance.window.viewInsets.bottom > 0.0)
{
// Keyboard is visible.
}
else
{
// Keyboard is not visible.
}
【讨论】:
在您的StatefullWidget 中,创建一个变量:
bool _keyboardVisible = false;
然后在build 小部件中初始化该变量;
@override
Widget build(BuildContext context) {
_keyboardVisible = MediaQuery.of(context).viewInsets.bottom != 0;
return child;
}
【讨论】:
您可以使用MediaQuery.of(context).viewInsets.bottom。请看下面的文档。
/// 被系统 UI 完全遮挡的显示部分,/// 通常被设备的键盘遮挡。 /// /// 当一个 移动设备的键盘可见
viewInsets.bottom/// 对应于键盘的顶部。 /// /// 这个值是 独立于[填充]:两个值都是 /// 从 [MediaQuery] 小部件边界的边缘。 /// 顶部的边界 [WidgetsApp] 创建的级别 MediaQuery 与 /// 相同 包含应用程序的窗口(通常是移动设备屏幕)。 ///
/// 另见: /// /// * [MediaQueryData],它提供了一些 有关此 /// 属性的其他详细信息以及它与 [填充]。 final EdgeInsets viewInsets;
【讨论】:
你可以使用 Flutter keyboard visibility plugin
@override
Widget build(BuildContext context) {
return KeyboardVisibilityBuilder(
builder: (context, isKeyboardVisible) {
return Text(
'The keyboard is: ${isKeyboardVisible ? 'VISIBLE' : 'NOT VISIBLE'}',
);
}
);
【讨论】:
这是我的解决方案,使用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);
}
}
【讨论】:
【讨论】:
我在这里找到了一个更简单的解决方案:
将DesiredBottomWidget放在Stack()和Positioned(top: somevalue)中,出现键盘时会隐藏。
例子:
Stack(
"Somewidget()",
Positioned(
top: "somevalue",
child: "DesiredBottomWidget()"),
),
【讨论】:
我使用了一种解决方法。我在输入中添加了一个 focusNode 并为其添加了一个侦听器。
在此处查看实现add focus listener to input。
【讨论】: