Repository navigation
Description
Steps to reproduce
DisplayFeatureSubScreen confines a dialog, bottom sheet or popup to one sub-screen of a foldable and wraps it in MediaQuery(data: mediaQuery.removeDisplayFeatures(closestSubScreen)). removeDisplayFeatures adjusts padding, viewInsets and viewPadding, and filters displayFeatures. It does not adjust size.
So a widget inside the dialog reads the width of the whole screen while occupying half of it. This runs as a widget test and passes today:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('MediaQuery.size is not reduced to the sub-screen', (
WidgetTester tester,
) async {
tester.view.devicePixelRatio = 1.0;
tester.view.physicalSize = const Size(800, 900);
// A 40px fold down the middle: the sub-screens are 0..380 and 420..800.
tester.view.displayFeatures = <DisplayFeature>[
const DisplayFeature(
bounds: Rect.fromLTRB(380, 0, 420, 900),
type: DisplayFeatureType.fold,
state: DisplayFeatureState.postureHalfOpened,
),
];
addTearDown(tester.view.reset);
late Size reported;
await tester.pumpWidget(
MaterialApp(
home: Builder(
builder: (BuildContext context) => ElevatedButton(
onPressed: () => showDialog<void>(
context: context,
anchorPoint: Offset.zero,
builder: (BuildContext inner) {
reported = MediaQuery.sizeOf(inner);
return const SizedBox.expand(key: Key('body'));
},
),
child: const Text('open'),
),
),
),
);
await tester.tap(find.text('open'));
await tester.pumpAndSettle();
final Rect body = tester.getRect(find.byKey(const Key('body')));
print('the dialog occupies -> ${body.width} x ${body.height}');
print('MediaQuery.sizeOf says -> ${reported.width} x ${reported.height}');
expect(body.width, 380);
expect(reported.width, 800); // passes today; 380 is what a caller expects
});
}Expected results
MediaQuery.sizeOf inside the sub-screen reports the size the child actually has — 380×900 here — or the documentation says that it deliberately does not, so callers know to reach for LayoutBuilder instead.
Actual results
the dialog occupies -> 380.0 x 900.0
MediaQuery.sizeOf says -> 800.0 x 900.0
Anything derived from it is off by the width of the other half plus the fold. A box asking for MediaQuery.sizeOf(context).width / 2 asks for 400 and is silently clamped to 380 — there is no overflow banner, just a layout that is quietly wrong.
Additional context
The doc comment on removeDisplayFeatures lists what it adjusts and does not mention size either way:
Creates a copy of this media query data by removing [displayFeatures] that are completely outside the given sub-screen and adjusting the [padding], [viewInsets] and [viewPadding] to be zero on the sides that are not included in the sub-screen.
Whether the fix is to narrow size or to document that it is not narrowed is a call for the team — the two have very different blast radii for apps already shipping on Android foldables.
Two things this is not, which I checked while measuring:
- The asymmetric insets are handled correctly. With
paddingofl=20 t=59 r=5 b=34and the same fold, a dialog on the left half lands at20..380and one on the right at420..795, so each side is honoured independently. - It is not iOS-specific. It reproduces on Android foldables today. It is worth raising now because the same code path is what
MediaQuery.displayFeatureswould drive on iPhone Duo ([iPhone Duo] Proposal: populate MediaQuery.displayFeatures on iOS for iPhone Duo (foldable) #192515), which ships on 23 October, so the number of apps hitting it is about to grow.
Reproduced on 3.44.6 stable and on a master checkout (3.48.0-1.0.pre-702); removeDisplayFeatures is unchanged between them.
flutter doctor
[✓] Flutter (Channel stable, 3.44.6, on macOS 26.5.2 25F84 darwin-arm64, locale es-CO)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
[✓] Xcode - develop for iOS and macOS (Xcode 26.1.1)
[✓] Chrome - develop for the web
[✓] Connected device (4 available)
[✓] Network resources
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNot started
Activity
mbcorona commentedon Sep 14, 2026
Hi @diegolopezrm, thanks for reporting. Confirmed on master: removeDisplayFeatures copyWith passes padding, viewInsets, viewPadding and displayFeatures but not size, so size stays the full screen.
Routing to the framework team for evaluation.
[-]`MediaQuery.sizeOf` reports the whole screen inside a dialog confined to one half of a foldable[/-][+][iPhone Duo] `MediaQuery.sizeOf` reports the whole screen inside a dialog confined to one half of a foldable[/+]preethi0228-git commentedon Sep 28, 2026
Hi,
I was able to reproduce the issue on the iPhone Duo Simulator. During my testing, I also observed some UI/layout issues with different components/screens, and I'm sharing a few screenshots as additional reference.
Thank you