我在Flutter中有一个页面,其中包含几个小部件,包括一个TextField(我们称其为View1)。当用户单击TextField时,我将重建仅显示TextField和键盘的页面(我们将其称为View2)。当用户完成TextField的操作后,我将重新构建页面,再次像以前一样显示所有小部件(尽管将其称为View1,但仍将其称为View3)。除了一件事,这工作正常。我得到一个临时的黄色/黑色指示器(在调试模式下),该指示器指示没有足够的空间来显示View3中的所有小部件。该指示器仅持续了很短的时间,我最终发现它似乎是因为Flutter试图在键盘尚未完成动画移动时显示所有小部件。键盘完成动画设置后,黄色/黑色条消失了,这说明了我认为为什么它只是短暂出现的原因。
在回调完成时请求View3的构建是很简洁的,该回调在键盘完成动画设置后执行,但我看不到有任何方法。也许我缺少什么?
我能想到的解决此问题的另一种方法是在构建View3之前插入一个延迟,以留出时间让键盘消失,但这似乎有点不客气。还有其他想法吗?
编辑
我添加了一个延迟,如下所示。不过,似乎还是有点古怪。
Timer(Duration(milliseconds: 500),(){setState((){});});
答案 0 :(得分:5)
尝试使用WidgetsBindingObserver
并重写didChangeMetrics
方法,如下所示:
class KeyboardTogglePage extends StatefulWidget {
@override
_KeyboardTogglePageState createState() => _KeyboardTogglePageState();
}
class _KeyboardTogglePageState extends State<KeyboardTogglePage>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
var isKeyboardOpen = false;
///
/// This routine is invoked when the window metrics have changed.
///
@override
void didChangeMetrics() {
final value = MediaQuery.of(context).viewInsets.bottom;
if (value > 0) {
if (isKeyboardOpen) {
_onKeyboardChanged(false);
}
isKeyboardOpen = false;
} else {
isKeyboardOpen = true;
_onKeyboardChanged(true);
}
}
_onKeyboardChanged(bool isVisible) {
if (isVisible) {
print("KEYBOARD VISIBLE");
} else {
print("KEYBOARD HIDDEN");
}
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: TextField(),
),
);
}
}
答案 1 :(得分:0)
当我将所有提到的解决方案放在一起时,对我来说效果很好:
class KeyboardTogglePage extends StatefulWidget {
@override
_KeyboardTogglePageState createState() => _KeyboardTogglePageState();
}
class _KeyboardTogglePageState extends State<KeyboardTogglePage>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
// This routine is invoked when the window metrics have changed.
@override
void didChangeMetrics() {
final value = WidgetsBinding.instance.window.viewInsets.bottom;
bool isVisible = value > 0;
print("KEYBOARD VISIBLE: ${isVisible}");
}
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: TextField(),
),
);
}
}