Unverified Commit efa69ba9 authored by Dan Field's avatar Dan Field Committed by GitHub

Add example for locking screen orientation in a letterboxing environment (#131266)

Android may choose to letterbox applications that lock orientation. This gets particularly bad on foldable devices, where a developer may want to lock orientation when the devices is folded and unlock when unfolded. However, if the app is letterboxed when unfolded, the `MediaQuery.of(context).size` will never report the full display size, only the letterboxed window size. This may result in an application getting "stuck" in portrait mode.

/cc @TytaniumDev
parent eb489122
......@@ -368,6 +368,74 @@ abstract final class SystemChrome {
///
/// ## Limitations
///
/// ### Android
///
/// Android screens may choose to [letterbox](https://developer.android.com/guide/practices/enhanced-letterboxing)
/// applications that lock orientation, particularly on larger screens. When
/// letterboxing occurs on Android, the [MediaQueryData.size] reports the
/// letterboxed size, not the full screen size. Applications that make
/// decisions about whether to lock orientation based on the screen size
/// must use the `display` property of the current [FlutterView].
///
/// ```dart
/// // A widget that locks the screen to portrait if it is less than 600
/// // logical pixels wide.
/// class MyApp extends StatefulWidget {
/// const MyApp({ super.key });
///
/// @override
/// State<MyApp> createState() => _MyAppState();
/// }
///
/// class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
/// ui.Display? _display;
/// static const double kOrientationLockBreakpoint = 600;
///
/// @override
/// void initState() {
/// super.initState();
/// WidgetsBinding.instance.addObserver(this);
/// }
///
/// @override
/// void didChangeDependencies() {
/// super.didChangeDependencies();
/// _display = View.maybeOf(context)?.display;
/// }
///
/// @override
/// void dispose() {
/// WidgetsBinding.instance.removeObserver(this);
/// _display = null;
/// super.dispose();
/// }
///
/// @override
/// void didChangeMetrics() {
/// final ui.Display? display = _display;
/// if (display == null) {
/// return;
/// }
/// if (display.size.width / display.devicePixelRatio < kOrientationLockBreakpoint) {
/// SystemChrome.setPreferredOrientations(<DeviceOrientation>[
/// DeviceOrientation.portraitUp,
/// ]);
/// } else {
/// SystemChrome.setPreferredOrientations(<DeviceOrientation>[]);
/// }
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return const MaterialApp(
/// home: Placeholder(),
/// );
/// }
/// }
/// ```
///
/// ### iOS
///
/// This setting will only be respected on iPad if multitasking is disabled.
///
/// You can decide to opt out of multitasking on iPad, then
......
......@@ -139,10 +139,15 @@ abstract mixin class WidgetsBindingObserver {
/// @override
/// void initState() {
/// super.initState();
/// WidgetsBinding.instance.addObserver(this);
/// }
///
/// @override
/// void didChangeDependencies() {
/// super.didChangeDependencies();
/// // [View.of] exposes the view from `WidgetsBinding.instance.platformDispatcher.views`
/// // into which this widget is drawn.
/// _lastSize = View.of(context).physicalSize;
/// WidgetsBinding.instance.addObserver(this);
/// }
///
/// @override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment