📱 Screen orientation

Common mistake

A common mistake is locking the application to portrait mode using SystemChrome.setPreferredOrientations. This forces users who have mounted their device in landscape (for example, wheelchair users with a fixed mount) to use the app in an orientation that doesn’t work for them.

🎯 Relevant elements

This guideline applies to the application as a whole and any screen that explicitly restricts orientation:

  • App-level orientation locks (SystemChrome.setPreferredOrientations)
  • Individual screens or routes that override orientation

WCAG Guideline

This guideline is based on WCAG 2.2 — 1.3.4 Orientation (Level AA). Content must not restrict its view and operation to a single display orientation unless a specific orientation is essential.


Solution

Avoid calling SystemChrome.setPreferredOrientations unless the orientation is truly essential to the functionality (e.g. a video player in fullscreen). Where possible, support both portrait and landscape.

// ❌ Don't - locks the app to portrait, ignoring user's device orientation
SystemChrome.setPreferredOrientations([
  DeviceOrientation.portraitUp,
]);

// ✅ Do - support all orientations (this is the default; no call needed)
SystemChrome.setPreferredOrientations([
  DeviceOrientation.portraitUp,
  DeviceOrientation.portraitDown,
  DeviceOrientation.landscapeLeft,
  DeviceOrientation.landscapeRight,
]);

If a specific screen genuinely requires a fixed orientation, restore the full set when leaving that screen:

@override
void initState() {
  super.initState();
  SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]);
}

@override
void dispose() {
  SystemChrome.setPreferredOrientations(DeviceOrientation.values);
  super.dispose();
}

Validation & Testing

Manual device testing

Rotate a physical device or emulator to both portrait and landscape while navigating through the app. Verify that no screen unexpectedly locks or resets to a fixed orientation.

flutter_test

testWidgets('screen does not restrict orientation', (tester) async {
  await tester.pumpWidget(MyApp());
  // Verify no SystemChrome orientation lock is applied by checking
  // that the widget tree renders correctly in both orientations.
  await tester.binding.setSurfaceSize(const Size(800, 400)); // landscape
  await tester.pump();
  expect(find.byType(MyHomePage), findsOneWidget);
});

This site uses Just the Docs, a documentation theme for Jekyll.