Flutter detect end of keyboard hide animation

旧城冷巷雨未停 提交于 2020-12-29 23:33:12

问题


I have a page in Flutter with a couple of widgets including a TextField (lets call this View1). When the user clicks the TextField I rebuild the page showing only the TextField and keyboard (lets call this View2). When the user finishes with the TextField I rebuild the page again showing all the widgets as before (lets call this View3 although note that it is the same as View1). This works fine except for one thing. I get a temporary yellow/black indicator (in debug mode) showing that there is not enough room to display all of the widgets in View3. The indicator only lasts a short time and I eventually worked out that it appears becasue Flutter is trying to display all the widgets while the keyboard has not yet finished animating away. Once the keyboard has finished animating away the yellow/black bar disappears and this explains I think why it only appears briefly.

It would be neat to request the build of View3 in a callback that executes when the keyboard has finished animating away but I don't see any way of doing that. Perhaps I'm missing something?

Another way I can think of to work around this would be to insert a delay before building View3 to allow time for the keyboard to disappear but this seems a little hacky. Has anyone any other ideas?

EDIT

I added a delay as follows and it works. Still seems a bit hacky though.

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

回答1:


Try using WidgetsBindingObserver and override the didChangeMetrics method like this:

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



回答2:


When I put all mentioned solutions together, it works well for me:

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


来源:https://stackoverflow.com/questions/52140698/flutter-detect-end-of-keyboard-hide-animation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!