Gabriel
Gabriel

Reputation: 386

Flutter - Media Query for keyboard height always returns zero

I'm trying to subtract the height of the keyboard from the height of the screen so I can apply that value to the height property of my listview container. This way my keyboard wont overlap my listview.

double sheetHeight;
double keyboardHeight;

I use MediaQuery and it returns 683 for the screen height, but always 0 for the keyboard height.

sheetHeight = MediaQuery.of(context).size.height;
keyboardHeight = MediaQuery.of(context).viewInsets.bottom;

This always makes my listview cover the entire screen, the opposite of what I want. Why does MediaQuery.of(context).viewInsets.bottom always return 0? I'm thinking it may have to do with the context but I'm not sure. It's also worth noting that my breakpoint isnt triggered when the keyboard initially comes up. I think this is also part of the problem. Any input or resources are greatly appreciated.

return Card(
  child: Container(
  height: sheetHeight - keyboardHeight,

To determine is the keyboard is visible, I use a keyboard_visibility package. If the keyboard is visible, I set the height with MediaQuery. If not, I set it to 0. While it returns true, the keyboard height still holds a value of 0. Is this the wrong approach?

super.initState();
WidgetsBinding.instance.addObserver(this);
KeyboardVisibilityNotification().addNewListener(
  onChange: (bool visible) {
    print(visible);
    if (visible == true) {
      keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
    } else {
      keyboardHeight = 0.0;
    }
  }
);

Upvotes: 6

Views: 10373

Answers (3)

Vincent Gigandet
Vincent Gigandet

Reputation: 948

MediaQuery.of(context).viewInsets.bottom always returns 0 because it refers keyboard height right before the keyboard actually visible. So you have to delay execution a little bit.

KeyboardVisibilityNotification().addNewListener(
  onChange: (bool visible) {
    print(visible);
    if (visible == true) {
      Future.delayed(const Duration(milliseconds: 300), () { 
        keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
      })
    } else {
      keyboardHeight = 0.0;
    }
  }
);

Upvotes: 0

Quanhua Guan
Quanhua Guan

Reputation: 463

Scaffold(resizeToAvoidBottomInset: false, body:...)

You need set the resizeToAvoidBottomInset to false, its default value is true.

Upvotes: 4

CopsOnRoad
CopsOnRoad

Reputation: 268314

MediaQuery.of(context).viewInsets.bottom

only returns value if your keyboard is visible on the screen, so if you are calling it without having the keyboard, it simply returns 0.

So make sure you only query bottom when the keyboard is up.


Edit:

Run this minimal reproducible code

Widget build(BuildContext context) {
  var bottom = MediaQuery.of(context).viewInsets.bottom;
  return Scaffold(
    appBar: AppBar(),
    body: Center(child: TextField(decoration: InputDecoration(hintText: "  ViewInsets.bottom =  $bottom"))),
  );
}

Output:

enter image description here

Upvotes: 10

Related Questions