In Flutter's MediaQueryData, how do padding, viewPadding and viewInsets differ, and what happens to each when the software keyboard opens?
answer
- partly versus fully obscured
- keyboard lives in viewInsets
- padding equals viewPadding minus viewInsets
- viewPadding ignores the keyboard
- Scaffold strips the body's bottom inset
basics
~20 sviewPadding is the area partly covered by system UI such as a notch or home indicator; viewInsets is the area fully covered, typically by the keyboard; padding is max(0, viewPadding - viewInsets). Opening the keyboard raises viewInsets.bottom and can drop padding.bottom to zero.
solid answer
~40 sAll three are `EdgeInsets` on `MediaQueryData`, read with `MediaQuery.viewPaddingOf`, `viewInsetsOf` and `paddingOf`. `viewPadding` is the region **partly** obscured by system UI — status bar, cutout, home indicator — and does not change when the keyboard appears. `viewInsets` is the region **fully** obscured, in practice the software keyboard: `viewInsets.bottom` becomes the keyboard's height when it is shown. `padding` is derived as `max(0, viewPadding - viewInsets)`, so once the keyboard covers the home-indicator area, `padding.bottom` drops to zero. By default `Scaffold` (`resizeToAvoidBottomInset` defaults to true) shrinks its body by `viewInsets.bottom` and removes that inset from the body's `MediaQuery`, so a widget inside the body usually reads zero.
code
dart · 15 linesimport 'package:flutter/material.dart';
Future<void> showQuickNoteSheet(BuildContext context) {
return showModalBottomSheet<void>(
context: context,
isScrollControlled: true,
builder: (BuildContext sheetContext) {
final double keyboard = MediaQuery.viewInsetsOf(sheetContext).bottom;
return Padding(
padding: EdgeInsets.fromLTRB(16, 16, 16, 16 + keyboard),
child: const TextField(autofocus: true, decoration: InputDecoration(hintText: 'Quick note')),
);
},
);
}go deeper
Remember that the keyboard shows up as viewInsets.bottom, while system bars show up as padding and viewPadding.
Explain the formula padding = max(0, viewPadding - viewInsets), walk through the keyboard example, and say what resizeToAvoidBottomInset does.
Diagnose keyboard bugs: a zero inset read inside a scaffold body, content jumping as padding collapses, sheets hidden behind the keyboard.
Decide where insets are consumed in shared screens so feature teams do not each reinvent keyboard handling and double-apply padding.
## Three kinds of edge Flutter describes the parts of the window it cannot fully use with three `EdgeInsets` values on `MediaQueryData`. Each has its own accessor, which also keeps rebuilds narrow: `MediaQuery.paddingOf`, `MediaQuery.viewPaddingOf` and `MediaQuery.viewInsetsOf`. | Field | Covered by | Changes when the keyboard opens? | |---|---|---| | `viewPadding` | partly obscuring system UI: status bar, cutout, home indicator | no | | `viewInsets` | fully obscuring system UI, usually the software keyboard | yes, `bottom` becomes the keyboard height | | `padding` | derived: `max(0, viewPadding - viewInsets)` | yes, can drop to zero | **Partly obscured** means the app may draw a background there, but interactive content should stay clear. **Fully obscured** means nothing drawn there is visible. ## A worked example Imagine a phone with a status bar and a home indicator: 1. Keyboard hidden: `viewPadding.bottom` is, say, 34; `viewInsets.bottom` is 0; `padding.bottom` is 34. 2. Keyboard shown, 300 pixels tall: `viewPadding.bottom` is still 34; `viewInsets.bottom` is 300; `padding.bottom` is `max(0, 34 - 300) = 0`. The keyboard now sits over the home-indicator strip, so there is no separate bottom padding left to avoid; `padding` reflects that. `viewPadding` keeps reporting the hardware's own inset, which is why `SafeArea`'s `maintainBottomViewPadding` switches to it to avoid a layout jump. ## How Scaffold uses them `Scaffold.resizeToAvoidBottomInset` defaults to `true`. With that default: - the body is laid out in a smaller area, reduced by `viewInsets.bottom`, so the keyboard does not cover it; - the body's `MediaQuery` has its bottom `viewInsets` removed, because the scaffold has already consumed them. The second point surprises people: `MediaQuery.viewInsetsOf(context).bottom` read inside a default scaffold's body is **zero**, even with the keyboard open. Read it above the scaffold, or in a route that is not inside that body, such as a modal bottom sheet, to see the real keyboard height. With `resizeToAvoidBottomInset: false`, the body keeps its full height, the keyboard may cover its lower part, and the body's `MediaQuery` keeps the real `viewInsets`. That suits a screen that wants to place its own input bar precisely. ## Practical uses - **Keep an input bar above the keyboard.** In a sheet or overlay, pad the bottom by `MediaQuery.viewInsetsOf(context).bottom`. - **Detect whether the keyboard is showing.** A non-zero `viewInsets.bottom`, read somewhere Scaffold has not stripped it, is the usual signal. - **Clear the system bars.** Use `padding` (or `SafeArea`) for status bar and home indicator. - **Stable bottom spacing.** Use `viewPadding.bottom` when content should not move as the keyboard opens and closes. ## Removing values for a subtree `MediaQuery.removePadding`, `MediaQuery.removeViewPadding` and `MediaQuery.removeViewInsets` create a new `MediaQuery` for a subtree with the chosen sides zeroed. Widgets that have "consumed" an inset — `SafeArea`, `Scaffold`, some app bars — use them so descendants do not apply the same inset twice. ## Mistakes to avoid - Using `padding.bottom` to position content above the keyboard; it is zero while the keyboard is open. - Reading `viewInsets` inside a default scaffold body and concluding the keyboard is hidden. - Reading `MediaQuery.of(context).viewInsets` in a large widget, making it rebuild on every unrelated metric change; use `viewInsetsOf`.
- Why does MediaQuery.viewInsetsOf(context).bottom read zero inside a Scaffold body while the keyboard is open?With the default `resizeToAvoidBottomInset: true`, `Scaffold` shrinks the body by the keyboard height and gives the body a `MediaQuery` with bottom `viewInsets` removed, because it has already consumed them. Read the value above the scaffold, or set `resizeToAvoidBottomInset: false` and handle the inset yourself.
- What does setting a Scaffold's resizeToAvoidBottomInset to false change?The body keeps its full height when the keyboard opens, so the keyboard can cover its lower part, and the body's `MediaQuery` keeps the real `viewInsets`. It suits screens that position their own input bar or deliberately let the keyboard overlap a background.
saying these in an interview costs you the question
- padding.bottom grows to the keyboard height when the keyboard opens.
- viewPadding shrinks while the software keyboard is visible.
- viewInsets reports the status bar and notch.
- MediaQuery size shrinks by the keyboard's height when it opens.
- resizeToAvoidBottomInset defaults to false on Scaffold.