skip to content

In Flutter's MediaQueryData, how do padding, viewPadding and viewInsets differ, and what happens to each when the software keyboard opens?

level: middleimportance: should knowfreq 40%

answer

  1. partly versus fully obscured
  2. keyboard lives in viewInsets
  3. padding equals viewPadding minus viewInsets
  4. viewPadding ignores the keyboard
  5. Scaffold strips the body's bottom inset

basics

~20 s

viewPadding 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 s

All 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 lines
dart
import '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

for a junior

Remember that the keyboard shows up as viewInsets.bottom, while system bars show up as padding and viewPadding.

for a middle

Explain the formula padding = max(0, viewPadding - viewInsets), walk through the keyboard example, and say what resizeToAvoidBottomInset does.

for a senior

Diagnose keyboard bugs: a zero inset read inside a scaffold body, content jumping as padding collapses, sheets hidden behind the keyboard.

for a principal

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.