In Flutter, what does OrientationBuilder actually measure, and why do the docs advise against switching whole layouts on orientation?
answer
- built on LayoutBuilder
- maxWidth greater than maxHeight
- square counts as portrait
- orientation derived from width and height
- width beats orientation
basics
~20 sOrientationBuilder 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 linesimport '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
Know that OrientationBuilder gives portrait or landscape to its builder and that landscape means wider than tall.
Explain that it wraps LayoutBuilder, compares the parent's constraints, treats square as portrait, and differs from the window-level MediaQuery value.
Push back on orientation-driven layouts and orientation locks, citing phones versus tablets, multi-window and letterboxing on large screens.
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.