mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Propagates Overlay's MediaQueryData to OverlayPortal child (#181579)
Widgets like Scaffold strip MediaQueryData causing widgets rendered in the Overlay to be obscured, e.g., by the software keyboard. [Related Issue - 142921](https://github.com/flutter/flutter/issues/142921) [Related Issue - 157664](https://github.com/flutter/flutter/issues/157664) This does not directly fix these two issues but appears to be an underlying issue with both which merited this being a separate PR. I have a separate fix for the MenuAnchor that I will supply in a follow up PR. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
656937e6f7
commit
1e029098f8
@ -26,6 +26,7 @@ import 'basic.dart';
|
||||
import 'framework.dart';
|
||||
import 'layout_builder.dart';
|
||||
import 'lookup_boundary.dart';
|
||||
import 'media_query.dart';
|
||||
import 'ticker_provider.dart';
|
||||
|
||||
/// The signature of the widget builder callback used in
|
||||
@ -2029,11 +2030,22 @@ class _OverlayPortalState extends State<OverlayPortal> {
|
||||
child: Semantics(traversalParentIdentifier: this, child: widget.child),
|
||||
);
|
||||
}
|
||||
|
||||
final _OverlayEntryLocation overlayLocation = _getLocation(zOrderIndex, widget.overlayLocation);
|
||||
final MediaQueryData overlayData = MediaQuery.of(overlayLocation._childModel.context);
|
||||
final MediaQueryData data = MediaQuery.of(context).copyWith(
|
||||
padding: overlayData.padding,
|
||||
viewInsets: overlayData.viewInsets,
|
||||
viewPadding: overlayData.viewPadding,
|
||||
);
|
||||
return _OverlayPortal(
|
||||
overlayLocation: _getLocation(zOrderIndex, widget.overlayLocation),
|
||||
overlayLocation: overlayLocation,
|
||||
overlayChild: _DeferredLayout(
|
||||
childIdentifier: this,
|
||||
child: Builder(builder: widget.overlayChildBuilder),
|
||||
child: MediaQuery(
|
||||
data: data,
|
||||
child: Builder(builder: widget.overlayChildBuilder),
|
||||
),
|
||||
),
|
||||
child: Semantics(traversalParentIdentifier: this, child: widget.child),
|
||||
);
|
||||
|
||||
@ -154,6 +154,129 @@ void main() {
|
||||
expect(directionSeenByOverlayChild, textDirection);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'OverlayPortal overlayChild located in root Overlay receives MediaQuery properties from root Overlay context',
|
||||
(WidgetTester tester) async {
|
||||
final controller = OverlayPortalController();
|
||||
const rootPadding = EdgeInsets.all(10);
|
||||
const innerPadding = EdgeInsets.all(20);
|
||||
|
||||
MediaQueryData? overlayChildData;
|
||||
OverlayEntry? outerEntry;
|
||||
OverlayEntry? innerEntry;
|
||||
addTearDown(() {
|
||||
outerEntry?.remove();
|
||||
outerEntry?.dispose();
|
||||
innerEntry?.remove();
|
||||
innerEntry?.dispose();
|
||||
});
|
||||
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(padding: rootPadding),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
outerEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return MediaQuery(
|
||||
data: const MediaQueryData(padding: innerPadding),
|
||||
child: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
innerEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return OverlayPortal(
|
||||
controller: controller,
|
||||
overlayLocation: OverlayChildLocation.rootOverlay,
|
||||
overlayChildBuilder: (BuildContext context) {
|
||||
overlayChildData = MediaQuery.of(context);
|
||||
return const SizedBox();
|
||||
},
|
||||
child: const SizedBox(),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
controller.show();
|
||||
await tester.pump();
|
||||
|
||||
expect(overlayChildData?.padding, rootPadding);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('OverlayPortal overlayChild receives MediaQuery properties from Overlay context', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
final controller = OverlayPortalController();
|
||||
const expectedPadding = EdgeInsets.all(10);
|
||||
const expectedViewInsets = EdgeInsets.only(bottom: 300);
|
||||
const expectedViewPadding = EdgeInsets.only(top: 50, bottom: 20);
|
||||
const expectedSize = Size(800, 600);
|
||||
|
||||
MediaQueryData? overlayChildData;
|
||||
OverlayEntry? entry;
|
||||
addTearDown(() {
|
||||
entry?.remove();
|
||||
entry?.dispose();
|
||||
});
|
||||
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: expectedPadding,
|
||||
viewInsets: expectedViewInsets,
|
||||
viewPadding: expectedViewPadding,
|
||||
size: expectedSize,
|
||||
),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
entry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
padding: EdgeInsets.zero,
|
||||
viewInsets: EdgeInsets.zero,
|
||||
viewPadding: EdgeInsets.zero,
|
||||
),
|
||||
child: OverlayPortal(
|
||||
controller: controller,
|
||||
overlayChildBuilder: (BuildContext context) {
|
||||
overlayChildData = MediaQuery.of(context);
|
||||
return const SizedBox();
|
||||
},
|
||||
child: const SizedBox(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
controller.show();
|
||||
await tester.pump();
|
||||
|
||||
expect(overlayChildData?.padding, expectedPadding);
|
||||
expect(overlayChildData?.viewInsets, expectedViewInsets);
|
||||
expect(overlayChildData?.viewPadding, expectedViewPadding);
|
||||
expect(overlayChildData?.size, expectedSize);
|
||||
});
|
||||
|
||||
testWidgets('The overlay portal update semantics does not dirty overlay', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user