Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter detect end of keyboard hide animation

Tags:

flutter

dart

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((){});});
like image 666
iBob101 Avatar asked Sep 02 '18 20:09

iBob101


1 Answers

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(),
        ),
      );
    }
  }
like image 75
diegoveloper Avatar answered Nov 06 '22 20:11

diegoveloper