skip to content

In Flutter, what does OrientationBuilder actually measure, and why do the docs advise against switching whole layouts on orientation?

level: middleimportance: should knowfreq 38%

answer

  1. built on LayoutBuilder
  2. maxWidth greater than maxHeight
  3. square counts as portrait
  4. orientation derived from width and height
  5. width beats orientation

basics

~20 s

OrientationBuilder compares its parent's maxWidth with maxHeight: wider is landscape, anything else portrait. Orientation says nothing about how much room exists — a landscape phone can be narrower than a portrait tablet — so layouts should branch on width with breakpoints.

solid answer

~40 s

`OrientationBuilder` is a thin wrapper over `LayoutBuilder`: it reports `Orientation.landscape` when `constraints.maxWidth > constraints.maxHeight`, and `portrait` otherwise, including for a square box. So it measures the **parent's slot**, not the device. `MediaQueryData.orientation` is likewise computed from the window's `size`, width against height. Flutter 3.41 added `DeviceOrientationBuilder`, which reads `MediaQuery.orientationOf`, the window-level value. The docs discourage switching an app's top-level layout on orientation because orientation is a ratio, not an amount: a phone turned sideways may be 800 by 360 while a tablet held upright is 800 by 1280. Branch on available width instead, and avoid locking orientation with `SystemChrome.setPreferredOrientations`, which can letterbox the app on foldables and large screens.

code

dart · 19 lines
dart
import 'package:flutter/material.dart';

class AttachmentGrid extends StatelessWidget {
  const AttachmentGrid({super.key, required this.thumbnails});

  final List<Widget> thumbnails;

  @override
  Widget build(BuildContext context) {
    return OrientationBuilder(
      builder: (BuildContext context, Orientation orientation) {
        return GridView.count(
          crossAxisCount: orientation == Orientation.landscape ? 4 : 2,
          children: thumbnails,
        );
      },
    );
  }
}

go deeper

for a junior

Know that OrientationBuilder gives portrait or landscape to its builder and that landscape means wider than tall.

for a middle

Explain that it wraps LayoutBuilder, compares the parent's constraints, treats square as portrait, and differs from the window-level MediaQuery value.

for a senior

Push back on orientation-driven layouts and orientation locks, citing phones versus tablets, multi-window and letterboxing on large screens.

for a principal

Make width-based breakpoints a design-system rule and budget the work to drop orientation locks before large-screen support becomes mandatory.

## What OrientationBuilder is `OrientationBuilder` is a `StatelessWidget` whose `build` returns a `LayoutBuilder`. Inside, it compares the incoming constraints: ```dart final Orientation orientation = constraints.maxWidth > constraints.maxHeight ? Orientation.landscape : Orientation.portrait; ``` Three consequences follow: - It measures the **parent's constraints**, not the screen. A `Column` child in a wide, short slot reports landscape even on an upright phone. - A **square** slot, or one where both maxima are infinite, reports **portrait**, because the comparison is strictly greater-than. - It rebuilds whenever those constraints change, like any `LayoutBuilder`. ## The other orientation sources | Source | What it compares | Scope | |---|---|---| | `OrientationBuilder` | parent's `maxWidth` vs `maxHeight` | this slot | | `MediaQueryData.orientation` / `MediaQuery.orientationOf` | window `size.width` vs `size.height` | the app's window | | `DeviceOrientationBuilder` (Flutter 3.41) | `MediaQuery.orientationOf` | the app's window | The API docs for `DeviceOrientationBuilder` call it the "device" orientation, but the value it reads is computed from the window's width and height. In split-screen that is the window's shape, which may differ from how the phone is held. ## Why orientation is a weak layout signal Orientation is a **ratio**, and layout decisions need an **amount**: 1. A phone in landscape might offer 800 by 360 logical pixels: wide, but too short for a tall list and a header. 2. A tablet in portrait might offer 800 by 1280: the same width, with plenty of height. 3. A resizable desktop or multi-window app can take any shape at all. If the app shows its two-pane layout "when landscape", the phone gets a cramped split and the upright tablet gets a stretched single column. Flutter's adaptive-design guidance therefore says to avoid using `MediaQuery`'s orientation or `OrientationBuilder` near the top of the tree to swap layouts, and to use `MediaQuery.sizeOf` or `LayoutBuilder` with width breakpoints instead — for example, a navigation change at 600 logical pixels. ## Where orientation is still useful - **Small, local tweaks.** A media card that puts the caption beside the image when its slot is wider than tall. - **Grid column counts** inside a region, when the ratio really is the input. - **Full-screen media**, such as a video player that fills the screen in landscape. Even then, `OrientationBuilder` inside the specific widget is better than a global orientation switch. ## Locking orientation `SystemChrome.setPreferredOrientations` restricts the orientations the app allows. The guidance is not to lock: - locked orientation can be an accessibility problem for users whose device is mounted in one position; - on large screens and foldables, Android may run a locked app in a compatibility mode and **letterbox** it — the window sits in the middle surrounded by black, and `MediaQuery` never reports the larger size; - locking postpones, but does not remove, the work of making the layout adaptive. ## Summary for an interview Say what `OrientationBuilder` compares, point out that it is local and that square means portrait, and then explain that width breakpoints, not orientation, should choose the app's structure.

  • What does OrientationBuilder report inside a 300 by 300 SizedBox, and why?
    `Orientation.portrait`. It returns landscape only when `maxWidth > maxHeight`; equal values fail the strict comparison, so a square slot counts as portrait.
  • How does DeviceOrientationBuilder differ from OrientationBuilder?
    Added in Flutter 3.41, `DeviceOrientationBuilder` reads `MediaQuery.orientationOf(context)`, so it reflects the app window's width against its height regardless of where it sits in the tree. `OrientationBuilder` uses `LayoutBuilder` and reflects its parent's constraints.

saying these in an interview costs you the question

  • OrientationBuilder reads the device's physical orientation sensor.
  • A square layout slot makes OrientationBuilder report landscape.
  • Landscape reliably means there is room for a two-pane layout.
  • Locking to portrait makes an app look right on foldables.
  • MediaQueryData.orientation is set by setPreferredOrientations.