颤振检测键盘隐藏动画的结束

Posted

技术标签:

【中文标题】颤振检测键盘隐藏动画的结束【英文标题】:Flutter detect end of keyboard hide animation 【发布时间】:2018-09-02 20:15:36 【问题描述】:

我在 Flutter 中有一个页面,其中包含几个小部件,包括一个 TextField(我们称之为 View1)。当用户单击 TextField 时,我重建仅显示 TextField 和键盘的页面(让我们称之为 View2)。当用户完成 TextField 后,我再次重建页面,显示所有小部件(尽管请注意它与 View1 相同,但我们称之为 View3)。除了一件事之外,这很好用。我得到一个临时的黄色/黑色指示器(在调试模式下),表明没有足够的空间来显示 View3 中的所有小部件。该指标只持续很短的时间,我最终发现它似乎是因为 Flutter 正在尝试显示所有小部件,而键盘还没有完成动画。一旦键盘完成动画,黄色/黑色条就会消失,这解释了我认为它为什么只出现短暂的原因。

在键盘完成动画后执行的回调中请求构建 View3 会很好,但我看不到任何这样做的方法。也许我错过了什么?

我能想到的解决此问题的另一种方法是在构建 View3 之前插入延迟,以便有时间让键盘消失,但这似乎有点 hacky。还有其他想法吗?

编辑

我添加了如下延迟,它可以工作。不过看起来还是有点老套。

Timer(Duration(milliseconds: 500),()setState(()););

【问题讨论】:

我同意添加时间延迟看起来很老套。听键盘和显示 View3 对我来说也听起来有点 hacky。你能显示在转换过程中发生的错误并且可能是一些代码吗? 【参考方案1】:

尝试使用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(),
        ),
      );
    
  

【讨论】:

这是对一般键盘更改做出反应的绝佳解决方案。我注意到final value = MediaQuery.of(context).viewInsets.bottom 得到的结果不正确,而final value = WidgetsBinding.instance.window.viewInsets.bottom 效果更好 嘿兄弟,谢谢。它比库更好地检查键盘是否打开。只有一个小错误。 if (value > 0) if (isKeyboardOpen) _onKeyboardChanged(false);->这是真的 isKeyboardOpen = false; 其他 isKeyboardOpen = true; _onKeyboardChanged(true);-> 这是假的 【参考方案2】:

当我将所有提到的解决方案放在一起时,它对我来说效果很好:

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(),
      ),
    );
  

【讨论】:

以上是关于颤振检测键盘隐藏动画的结束的主要内容,如果未能解决你的问题,请参考以下文章

键盘出现时隐藏元素

键盘隐藏另一个视图的文本字段动画

键盘显示和隐藏上的动画自动布局约束

动画结束时如何隐藏视图?

在键盘隐藏的颤动页面文本字段中

java 检测键盘的打开/隐藏事件