Add MediaQuery to View (#118004)
* Add MediaQuery to View
* unify API
* fix test
* add test
* comment
* better doc
* Apply suggestions from code review
Co-authored-by: Greg Spencer <gspencergoog@users.noreply.github.com>
Co-authored-by: Greg Spencer <gspencergoog@users.noreply.github.com>
diff --git a/packages/flutter/lib/src/widgets/app.dart b/packages/flutter/lib/src/widgets/app.dart
index 931623c..9e915a7 100644
--- a/packages/flutter/lib/src/widgets/app.dart
+++ b/packages/flutter/lib/src/widgets/app.dart
@@ -1730,8 +1730,7 @@
child: title,
);
- final MediaQueryData? data = MediaQuery.maybeOf(context);
- if (!widget.useInheritedMediaQuery || data == null) {
+ if (!widget.useInheritedMediaQuery || MediaQuery.maybeOf(context) == null) {
child = MediaQuery.fromWindow(
child: child,
);
diff --git a/packages/flutter/lib/src/widgets/media_query.dart b/packages/flutter/lib/src/widgets/media_query.dart
index 890dd98..68f38b6 100644
--- a/packages/flutter/lib/src/widgets/media_query.dart
+++ b/packages/flutter/lib/src/widgets/media_query.dart
@@ -138,8 +138,8 @@
class MediaQueryData {
/// Creates data for a media query with explicit values.
///
- /// Consider using [MediaQueryData.fromWindow] to create data based on a
- /// [dart:ui.PlatformDispatcher].
+ /// Consider using [MediaQueryData.fromView] to create data based on a
+ /// [dart:ui.FlutterView].
const MediaQueryData({
this.size = Size.zero,
this.devicePixelRatio = 1.0,
@@ -167,24 +167,60 @@
/// window's metrics change. For example, see
/// [WidgetsBindingObserver.didChangeMetrics] or
/// [dart:ui.PlatformDispatcher.onMetricsChanged].
- MediaQueryData.fromWindow(ui.FlutterView window)
- : size = window.physicalSize / window.devicePixelRatio,
- devicePixelRatio = window.devicePixelRatio,
- textScaleFactor = window.platformDispatcher.textScaleFactor,
- platformBrightness = window.platformDispatcher.platformBrightness,
- padding = EdgeInsets.fromWindowPadding(window.padding, window.devicePixelRatio),
- viewPadding = EdgeInsets.fromWindowPadding(window.viewPadding, window.devicePixelRatio),
- viewInsets = EdgeInsets.fromWindowPadding(window.viewInsets, window.devicePixelRatio),
- systemGestureInsets = EdgeInsets.fromWindowPadding(window.systemGestureInsets, window.devicePixelRatio),
- accessibleNavigation = window.platformDispatcher.accessibilityFeatures.accessibleNavigation,
- invertColors = window.platformDispatcher.accessibilityFeatures.invertColors,
- disableAnimations = window.platformDispatcher.accessibilityFeatures.disableAnimations,
- boldText = window.platformDispatcher.accessibilityFeatures.boldText,
- highContrast = window.platformDispatcher.accessibilityFeatures.highContrast,
- alwaysUse24HourFormat = window.platformDispatcher.alwaysUse24HourFormat,
- navigationMode = NavigationMode.traditional,
- gestureSettings = DeviceGestureSettings.fromWindow(window),
- displayFeatures = window.displayFeatures;
+ factory MediaQueryData.fromWindow(ui.FlutterView window) => MediaQueryData.fromView(window);
+
+ /// Creates data for a [MediaQuery] based on the given `view`.
+ ///
+ /// If provided, the `platformData` is used to fill in the platform-specific
+ /// aspects of the newly created [MediaQueryData]. If `platformData` is null,
+ /// the `view`'s [PlatformDispatcher] is consulted to construct the
+ /// platform-specific data.
+ ///
+ /// Data which is exposed directly on the [FlutterView] is considered
+ /// view-specific. Data which is only exposed via the
+ /// [FlutterView.platformDispatcher] property is considered platform-specific.
+ ///
+ /// Callers of this method should ensure that they also register for
+ /// notifications so that the [MediaQueryData] can be updated when any data
+ /// used to construct it changes. Notifications to consider are:
+ ///
+ /// * [WidgetsBindingObserver.didChangeMetrics] or
+ /// [dart:ui.PlatformDispatcher.onMetricsChanged],
+ /// * [WidgetsBindingObserver.didChangeAccessibilityFeatures] or
+ /// [dart:ui.PlatformDispatcher.onAccessibilityFeaturesChanged],
+ /// * [WidgetsBindingObserver.didChangeTextScaleFactor] or
+ /// [dart:ui.PlatformDispatcher.onTextScaleFactorChanged],
+ /// * [WidgetsBindingObserver.didChangePlatformBrightness] or
+ /// [dart:ui.PlatformDispatcher.onPlatformBrightnessChanged].
+ ///
+ /// The last three notifications are only relevant if no `platformData` is
+ /// provided. If `platformData` is provided, callers should ensure to call
+ /// this method again when it changes to keep the constructed [MediaQueryData]
+ /// updated.
+ ///
+ /// See also:
+ ///
+ /// * [MediaQuery.fromView], which constructs [MediaQueryData] from a provided
+ /// [FlutterView], makes it available to descendant widgets, and sets up
+ /// the appropriate notification listeners to keep the data updated.
+ MediaQueryData.fromView(ui.FlutterView view, {MediaQueryData? platformData})
+ : size = view.physicalSize / view.devicePixelRatio,
+ devicePixelRatio = view.devicePixelRatio,
+ textScaleFactor = platformData?.textScaleFactor ?? view.platformDispatcher.textScaleFactor,
+ platformBrightness = platformData?.platformBrightness ?? view.platformDispatcher.platformBrightness,
+ padding = EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio),
+ viewPadding = EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio),
+ viewInsets = EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio),
+ systemGestureInsets = EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio),
+ accessibleNavigation = platformData?.accessibleNavigation ?? view.platformDispatcher.accessibilityFeatures.accessibleNavigation,
+ invertColors = platformData?.invertColors ?? view.platformDispatcher.accessibilityFeatures.invertColors,
+ disableAnimations = platformData?.disableAnimations ?? view.platformDispatcher.accessibilityFeatures.disableAnimations,
+ boldText = platformData?.boldText ?? view.platformDispatcher.accessibilityFeatures.boldText,
+ highContrast = platformData?.highContrast ?? view.platformDispatcher.accessibilityFeatures.highContrast,
+ alwaysUse24HourFormat = platformData?.alwaysUse24HourFormat ?? view.platformDispatcher.alwaysUse24HourFormat,
+ navigationMode = platformData?.navigationMode ?? NavigationMode.traditional,
+ gestureSettings = DeviceGestureSettings.fromWindow(view),
+ displayFeatures = view.displayFeatures;
/// The size of the media in logical pixels (e.g, the size of the screen).
///
@@ -889,17 +925,43 @@
/// and its dependents are updated when `window` changes, instead of
/// rebuilding the whole widget tree.
///
- /// This should be inserted into the widget tree when the [MediaQuery] view
- /// padding is consumed by a widget in such a way that the view padding is no
- /// longer exposed to the widget's descendants or siblings.
- ///
/// The [child] argument is required and must not be null.
static Widget fromWindow({
Key? key,
required Widget child,
}) {
- return _MediaQueryFromWindow(
+ return _MediaQueryFromView(
key: key,
+ view: WidgetsBinding.instance.window,
+ ignoreParentData: true,
+ child: child,
+ );
+ }
+
+ /// Wraps the [child] in a [MediaQuery] which is built using data from the
+ /// provided [view].
+ ///
+ /// The [MediaQuery] is constructed using the platform-specific data of the
+ /// surrounding [MediaQuery] and the view-specific data of the provided
+ /// [view]. If no surrounding [MediaQuery] exists, the platform-specific data
+ /// is generated from the [PlatformDispatcher] associated with the provided
+ /// [view]. Any information that's exposed via the [PlatformDispatcher] is
+ /// considered platform-specific. Data exposed directly on the [FlutterView]
+ /// (excluding its [FlutterView.platformDispatcher] property) is considered
+ /// view-specific.
+ ///
+ /// The injected [MediaQuery] automatically updates when any of the data used
+ /// to construct it changes.
+ ///
+ /// The [view] and [child] argument is required and must not be null.
+ static Widget fromView({
+ Key? key,
+ required FlutterView view,
+ required Widget child,
+ }) {
+ return _MediaQueryFromView(
+ key: key,
+ view: view,
child: child,
);
}
@@ -1399,94 +1461,102 @@
directional,
}
-/// Provides a [MediaQuery] which is built and updated using the latest
-/// [WidgetsBinding.window] values.
-///
-/// Receives `window` updates by listening to [WidgetsBinding].
-///
-/// The standalone widget ensures that it rebuilds **only** [MediaQuery] and
-/// its dependents when `window` changes, instead of rebuilding the entire
-/// widget tree.
-///
-/// It is used by [WidgetsApp] if no other [MediaQuery] is available above it.
-///
-/// See also:
-///
-/// * [MediaQuery], which establishes a subtree in which media queries resolve
-/// to a [MediaQueryData].
-class _MediaQueryFromWindow extends StatefulWidget {
- /// Creates a [_MediaQueryFromWindow] that provides a [MediaQuery] to its
- /// descendants using the `window` to keep [MediaQueryData] up to date.
- ///
- /// The [child] must not be null.
- const _MediaQueryFromWindow({
+class _MediaQueryFromView extends StatefulWidget {
+ const _MediaQueryFromView({
super.key,
+ required this.view,
+ this.ignoreParentData = false,
required this.child,
});
- /// {@macro flutter.widgets.ProxyWidget.child}
+ final FlutterView view;
+ final bool ignoreParentData;
final Widget child;
@override
- State<_MediaQueryFromWindow> createState() => _MediaQueryFromWindowState();
+ State<_MediaQueryFromView> createState() => _MediaQueryFromViewState();
}
-class _MediaQueryFromWindowState extends State<_MediaQueryFromWindow> with WidgetsBindingObserver {
+class _MediaQueryFromViewState extends State<_MediaQueryFromView> with WidgetsBindingObserver {
+ MediaQueryData? _parentData;
+ MediaQueryData? _data;
+
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
- // ACCESSIBILITY
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ _updateParentData();
+ _updateData();
+ assert(_data != null);
+ }
+
+ @override
+ void didUpdateWidget(_MediaQueryFromView oldWidget) {
+ super.didUpdateWidget(oldWidget);
+ if (widget.ignoreParentData != oldWidget.ignoreParentData) {
+ _updateParentData();
+ }
+ if (_data == null || oldWidget.view != widget.view) {
+ _updateData();
+ }
+ assert(_data != null);
+ }
+
+ void _updateParentData() {
+ _parentData = widget.ignoreParentData ? null : MediaQuery.maybeOf(context);
+ _data = null; // _updateData must be called again after changing parent data.
+ }
+
+ void _updateData() {
+ final MediaQueryData newData = MediaQueryData.fromView(widget.view, platformData: _parentData);
+ if (newData != _data) {
+ setState(() {
+ _data = newData;
+ });
+ }
+ }
@override
void didChangeAccessibilityFeatures() {
- setState(() {
- // The properties of window have changed. We use them in our build
- // function, so we need setState(), but we don't cache anything locally.
- });
+ // If we have a parent, it dictates our accessibility features. If we don't
+ // have a parent, we get our accessibility features straight from the
+ // PlatformDispatcher and need to update our data in response to the
+ // PlatformDispatcher changing its accessibility features setting.
+ if (_parentData == null) {
+ _updateData();
+ }
}
- // METRICS
-
@override
void didChangeMetrics() {
- setState(() {
- // The properties of window have changed. We use them in our build
- // function, so we need setState(), but we don't cache anything locally.
- });
+ _updateData();
}
@override
void didChangeTextScaleFactor() {
- setState(() {
- // The textScaleFactor property of window has changed. We reference
- // window in our build function, so we need to call setState(), but
- // we don't need to cache anything locally.
- });
+ // If we have a parent, it dictates our text scale factor. If we don't have
+ // a parent, we get our text scale factor from the PlatformDispatcher and
+ // need to update our data in response to the PlatformDispatcher changing
+ // its text scale factor setting.
+ if (_parentData == null) {
+ _updateData();
+ }
}
- // RENDERING
@override
void didChangePlatformBrightness() {
- setState(() {
- // The platformBrightness property of window has changed. We reference
- // window in our build function, so we need to call setState(), but
- // we don't need to cache anything locally.
- });
- }
-
- @override
- Widget build(BuildContext context) {
- MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
- if (!kReleaseMode) {
- data = data.copyWith(platformBrightness: debugBrightnessOverride);
+ // If we have a parent, it dictates our platform brightness. If we don't
+ // have a parent, we get our platform brightness from the PlatformDispatcher
+ // and need to update our data in response to the PlatformDispatcher
+ // changing its platform brightness setting.
+ if (_parentData == null) {
+ _updateData();
}
- return MediaQuery(
- data: data,
- child: widget.child,
- );
}
@override
@@ -1494,4 +1564,18 @@
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
+
+ @override
+ Widget build(BuildContext context) {
+ MediaQueryData effectiveData = _data!;
+ // If we get our platformBrightness from the PlatformDispatcher (i.e. we have no parentData) replace it
+ // with the debugBrightnessOverride in non-release mode.
+ if (!kReleaseMode && _parentData == null && effectiveData.platformBrightness != debugBrightnessOverride) {
+ effectiveData = effectiveData.copyWith(platformBrightness: debugBrightnessOverride);
+ }
+ return MediaQuery(
+ data: effectiveData,
+ child: widget.child,
+ );
+ }
}
diff --git a/packages/flutter/lib/src/widgets/view.dart b/packages/flutter/lib/src/widgets/view.dart
index 0a20685..14f87c6 100644
--- a/packages/flutter/lib/src/widgets/view.dart
+++ b/packages/flutter/lib/src/widgets/view.dart
@@ -6,10 +6,14 @@
import 'framework.dart';
import 'lookup_boundary.dart';
+import 'media_query.dart';
/// Injects a [FlutterView] into the tree and makes it available to descendants
/// within the same [LookupBoundary] via [View.of] and [View.maybeOf].
///
+/// The provided [child] is wrapped in a [MediaQuery] constructed from the given
+/// [view].
+///
/// In a future version of Flutter, the functionality of this widget will be
/// extended to actually bootstrap the render tree that is going to be rendered
/// into the provided [view]. This will enable rendering content into multiple
@@ -20,15 +24,26 @@
/// [FlutterView] must never exist within the same widget tree at the same time.
/// Internally, this limitation is enforced by a [GlobalObjectKey] that derives
/// its identity from the [view] provided to this widget.
-class View extends InheritedWidget {
+class View extends StatelessWidget {
/// Injects the provided [view] into the widget tree.
- View({required this.view, required super.child}) : super(key: GlobalObjectKey(view));
+ View({required this.view, required this.child}) : super(key: GlobalObjectKey(view));
/// The [FlutterView] to be injected into the tree.
final FlutterView view;
+ /// {@macro flutter.widgets.ProxyWidget.child}
+ final Widget child;
+
@override
- bool updateShouldNotify(View oldWidget) => view != oldWidget.view;
+ Widget build(BuildContext context) {
+ return _ViewScope(
+ view: view,
+ child: MediaQuery.fromView(
+ view: view,
+ child: child,
+ ),
+ );
+ }
/// Returns the [FlutterView] that the provided `context` will render into.
///
@@ -47,7 +62,7 @@
/// * [View.of], which throws instead of returning null if no [FlutterView]
/// is found.
static FlutterView? maybeOf(BuildContext context) {
- return LookupBoundary.dependOnInheritedWidgetOfExactType<View>(context)?.view;
+ return LookupBoundary.dependOnInheritedWidgetOfExactType<_ViewScope>(context)?.view;
}
/// Returns the [FlutterView] that the provided `context` will render into.
@@ -70,7 +85,7 @@
final FlutterView? result = maybeOf(context);
assert(() {
if (result == null) {
- final bool hiddenByBoundary = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<View>(context);
+ final bool hiddenByBoundary = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<_ViewScope>(context);
final List<DiagnosticsNode> information = <DiagnosticsNode>[
if (hiddenByBoundary) ...<DiagnosticsNode>[
ErrorSummary('View.of() was called with a context that does not have access to a View widget.'),
@@ -92,3 +107,12 @@
return result!;
}
}
+
+class _ViewScope extends InheritedWidget {
+ const _ViewScope({required this.view, required super.child});
+
+ final FlutterView view;
+
+ @override
+ bool updateShouldNotify(_ViewScope oldWidget) => view != oldWidget.view;
+}
diff --git a/packages/flutter/test/material/debug_test.dart b/packages/flutter/test/material/debug_test.dart
index b955a1c..c9f7a3b 100644
--- a/packages/flutter/test/material/debug_test.dart
+++ b/packages/flutter/test/material/debug_test.dart
@@ -193,7 +193,7 @@
' Semantics\n'
' Localizations\n'
' MediaQuery\n'
- ' _MediaQueryFromWindow\n'
+ ' _MediaQueryFromView\n'
' Semantics\n'
' _FocusInheritedScope\n'
' Focus\n'
@@ -235,6 +235,9 @@
' HeroControllerScope\n'
' ScrollConfiguration\n'
' MaterialApp\n'
+ ' MediaQuery\n'
+ ' _MediaQueryFromView\n'
+ ' _ViewScope\n'
' View-[GlobalObjectKey TestWindow#00000]\n'
' [root]\n'
' Typically, the Scaffold widget is introduced by the MaterialApp\n'
@@ -251,18 +254,15 @@
);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
- child: MediaQuery(
- data: const MediaQueryData(),
- child: ScaffoldMessenger(
- key: scaffoldMessengerKey,
- child: Builder(
- builder: (BuildContext context) {
- return Scaffold(
- key: scaffoldKey,
- body: Container(),
- );
- },
- ),
+ child: ScaffoldMessenger(
+ key: scaffoldMessengerKey,
+ child: Builder(
+ builder: (BuildContext context) {
+ return Scaffold(
+ key: scaffoldKey,
+ body: Container(),
+ );
+ },
),
),
));
@@ -278,12 +278,9 @@
// Pump widget to rebuild without ScaffoldMessenger
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
- child: MediaQuery(
- data: const MediaQueryData(),
- child: Scaffold(
- key: scaffoldKey,
- body: Container(),
- ),
+ child: Scaffold(
+ key: scaffoldKey,
+ body: Container(),
),
));
// Tap SnackBarAction to dismiss.
@@ -378,8 +375,10 @@
' ScrollNotificationObserver\n'
' _ScaffoldScope\n'
' Scaffold-[LabeledGlobalKey<ScaffoldState>#00000]\n'
- ' MediaQuery\n'
' Directionality\n'
+ ' MediaQuery\n'
+ ' _MediaQueryFromView\n'
+ ' _ViewScope\n'
' View-[GlobalObjectKey TestWindow#00000]\n'
' [root]\n'
' Typically, the ScaffoldMessenger widget is introduced by the\n'
diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart
index 12709de..f905d0c 100644
--- a/packages/flutter/test/material/scaffold_test.dart
+++ b/packages/flutter/test/material/scaffold_test.dart
@@ -136,12 +136,6 @@
),
);
}
- await tester.pumpWidget(boilerplate(Scaffold(
- appBar: AppBar(title: const Text('Title')),
- body: Container(key: bodyKey),
- ),
- ));
- expect(tester.takeException(), isFlutterError);
await tester.pumpWidget(MaterialApp(
home: Scaffold(
@@ -2391,24 +2385,21 @@
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
- child: MediaQuery(
- data: const MediaQueryData(),
- child: Scaffold(
- body: Builder(
- builder: (BuildContext context) {
- return GestureDetector(
- key: tapTarget,
- onTap: () {
- ScaffoldMessenger.of(context);
- },
- behavior: HitTestBehavior.opaque,
- child: const SizedBox(
- height: 100.0,
- width: 100.0,
- ),
- );
- },
- ),
+ child: Scaffold(
+ body: Builder(
+ builder: (BuildContext context) {
+ return GestureDetector(
+ key: tapTarget,
+ onTap: () {
+ ScaffoldMessenger.of(context);
+ },
+ behavior: HitTestBehavior.opaque,
+ child: const SizedBox(
+ height: 100.0,
+ width: 100.0,
+ ),
+ );
+ },
),
),
));
@@ -2459,8 +2450,10 @@
' ScrollNotificationObserver\n'
' _ScaffoldScope\n'
' Scaffold\n'
- ' MediaQuery\n'
' Directionality\n'
+ ' MediaQuery\n'
+ ' _MediaQueryFromView\n'
+ ' _ViewScope\n'
' View-[GlobalObjectKey TestWindow#e6136]\n'
' [root]\n'
' Typically, the ScaffoldMessenger widget is introduced by the\n'
diff --git a/packages/flutter/test/widgets/animated_container_test.dart b/packages/flutter/test/widgets/animated_container_test.dart
index 476df62..ce9f17c 100644
--- a/packages/flutter/test/widgets/animated_container_test.dart
+++ b/packages/flutter/test/widgets/animated_container_test.dart
@@ -77,7 +77,7 @@
' │ decoration: BoxDecoration:\n'
' │ color: Color(0xff0000ff)\n'
' │ configuration: ImageConfiguration(bundle:\n'
- ' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+ ' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
' │ android)\n'
' │\n'
' └─child: RenderLimitedBox#00000\n'
diff --git a/packages/flutter/test/widgets/app_test.dart b/packages/flutter/test/widgets/app_test.dart
index 6bcf5c1..6d58a4a 100644
--- a/packages/flutter/test/widgets/app_test.dart
+++ b/packages/flutter/test/widgets/app_test.dart
@@ -644,6 +644,32 @@
expect(MediaQuery.of(capturedContext), isNotNull);
});
+ testWidgets("WidgetsApp doesn't have dependency on MediaQuery", (WidgetTester tester) async {
+ int routeBuildCount = 0;
+
+ final Widget widget = WidgetsApp(
+ color: const Color.fromARGB(255, 255, 255, 255),
+ onGenerateRoute: (_) {
+ return PageRouteBuilder<void>(pageBuilder: (_, __, ___) {
+ routeBuildCount++;
+ return const Placeholder();
+ });
+ },
+ );
+
+ await tester.pumpWidget(
+ MediaQuery(data: const MediaQueryData(textScaleFactor: 10), child: widget),
+ );
+
+ expect(routeBuildCount, equals(1));
+
+ await tester.pumpWidget(
+ MediaQuery(data: const MediaQueryData(textScaleFactor: 20), child: widget),
+ );
+
+ expect(routeBuildCount, equals(1));
+ });
+
testWidgets('WidgetsApp provides meta based shortcuts for iOS and macOS', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
final SelectAllSpy selectAllSpy = SelectAllSpy();
diff --git a/packages/flutter/test/widgets/container_test.dart b/packages/flutter/test/widgets/container_test.dart
index 7e3a507..28c3ef6 100644
--- a/packages/flutter/test/widgets/container_test.dart
+++ b/packages/flutter/test/widgets/container_test.dart
@@ -78,7 +78,7 @@
' │ decoration: BoxDecoration:\n'
' │ color: Color(0x7f0000ff)\n'
' │ configuration: ImageConfiguration(bundle:\n'
- ' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+ ' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
' │ android)\n'
' │\n'
' └─child: _RenderColoredBox#00000\n'
@@ -114,7 +114,7 @@
' decoration: BoxDecoration:\n'
' color: Color(0xffffff00)\n'
' configuration: ImageConfiguration(bundle:\n'
- ' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+ ' PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
' android)\n',
),
);
@@ -123,7 +123,8 @@
box.toStringDeep(),
equalsIgnoringHashCodes(
'RenderPadding#00000 relayoutBoundary=up1\n'
- ' │ creator: Padding ← Container ← Align ← View-[GlobalObjectKey\n'
+ ' │ creator: Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
' │ TestWindow#00000] ← [root]\n'
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
@@ -132,6 +133,7 @@
' │\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
+ ' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: offset=Offset(5.0, 5.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
@@ -140,20 +142,21 @@
' │\n'
' └─child: RenderDecoratedBox#00000\n'
' │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\n'
- ' │ Align ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ Align ← MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
+ ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ size: Size(53.0, 78.0)\n'
' │ decoration: BoxDecoration:\n'
' │ color: Color(0x7f0000ff)\n'
' │ configuration: ImageConfiguration(bundle:\n'
- ' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+ ' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
' │ android)\n'
' │\n'
' └─child: _RenderColoredBox#00000\n'
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
- ' │ Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
- ' │ [root]\n'
+ ' │ Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
+ ' │ _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ size: Size(53.0, 78.0)\n'
@@ -161,8 +164,8 @@
' │\n'
' └─child: RenderPadding#00000\n'
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
- ' │ Padding ← Container ← Align ← View-[GlobalObjectKey\n'
- ' │ TestWindow#00000] ← [root]\n'
+ ' │ Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
+ ' │ ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ size: Size(53.0, 78.0)\n'
@@ -170,8 +173,9 @@
' │\n'
' └─child: RenderPositionedBox#00000\n'
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
- ' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+ ' │ TestWindow#00000] ← ⋯\n'
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
' │ size: Size(39.0, 64.0)\n'
@@ -181,8 +185,8 @@
' │\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
- ' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← ⋯\n'
' │ parentData: offset=Offset(14.0, 31.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
' │ size: Size(25.0, 33.0)\n'
@@ -191,15 +195,15 @@
' └─child: RenderDecoratedBox#00000\n'
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' MediaQuery ← _MediaQueryFromView ← ⋯\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
' size: Size(25.0, 33.0)\n'
' decoration: BoxDecoration:\n'
' color: Color(0xffffff00)\n'
' configuration: ImageConfiguration(bundle:\n'
- ' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
- ' android)\n'
+ ' PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
+ ' android)\n',
),
);
@@ -207,7 +211,8 @@
box.toStringDeep(minLevel: DiagnosticLevel.fine),
equalsIgnoringHashCodes(
'RenderPadding#00000 relayoutBoundary=up1\n'
- ' │ creator: Padding ← Container ← Align ← View-[GlobalObjectKey\n'
+ ' │ creator: Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
' │ TestWindow#00000] ← [root]\n'
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
@@ -219,6 +224,7 @@
' │\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
+ ' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: offset=Offset(5.0, 5.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
@@ -229,7 +235,8 @@
' │\n'
' └─child: RenderDecoratedBox#00000\n'
' │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\n'
- ' │ Align ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ Align ← MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
+ ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ layer: null\n'
@@ -244,13 +251,13 @@
' │ gradient: null\n'
' │ shape: rectangle\n'
' │ configuration: ImageConfiguration(bundle:\n'
- ' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+ ' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
' │ android)\n'
' │\n'
' └─child: _RenderColoredBox#00000\n'
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
- ' │ Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
- ' │ [root]\n'
+ ' │ Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
+ ' │ _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ layer: null\n'
@@ -260,8 +267,8 @@
' │\n'
' └─child: RenderPadding#00000\n'
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
- ' │ Padding ← Container ← Align ← View-[GlobalObjectKey\n'
- ' │ TestWindow#00000] ← [root]\n'
+ ' │ Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
+ ' │ ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ layer: null\n'
@@ -272,8 +279,9 @@
' │\n'
' └─child: RenderPositionedBox#00000\n'
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
- ' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+ ' │ TestWindow#00000] ← ⋯\n'
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
' │ layer: null\n'
@@ -286,8 +294,8 @@
' │\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
- ' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← ⋯\n'
' │ parentData: offset=Offset(14.0, 31.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
' │ layer: null\n'
@@ -298,7 +306,7 @@
' └─child: RenderDecoratedBox#00000\n'
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' MediaQuery ← _MediaQueryFromView ← ⋯\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
' layer: null\n'
@@ -313,8 +321,8 @@
' gradient: null\n'
' shape: rectangle\n'
' configuration: ImageConfiguration(bundle:\n'
- ' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
- ' android)\n'
+ ' PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
+ ' android)\n',
),
);
@@ -323,7 +331,8 @@
equalsIgnoringHashCodes(
'RenderPadding#00000 relayoutBoundary=up1\n'
' │ needsCompositing: false\n'
- ' │ creator: Padding ← Container ← Align ← View-[GlobalObjectKey\n'
+ ' │ creator: Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
' │ TestWindow#00000] ← [root]\n'
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
@@ -338,6 +347,7 @@
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
' │ needsCompositing: false\n'
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
+ ' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: offset=Offset(5.0, 5.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
@@ -351,7 +361,8 @@
' └─child: RenderDecoratedBox#00000\n'
' │ needsCompositing: false\n'
' │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\n'
- ' │ Align ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ Align ← MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
+ ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ layer: null\n'
@@ -368,14 +379,14 @@
' │ gradient: null\n'
' │ shape: rectangle\n'
' │ configuration: ImageConfiguration(bundle:\n'
- ' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
+ ' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
' │ android)\n'
' │\n'
' └─child: _RenderColoredBox#00000\n'
' │ needsCompositing: false\n'
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
- ' │ Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
- ' │ [root]\n'
+ ' │ Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
+ ' │ _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ layer: null\n'
@@ -388,8 +399,8 @@
' └─child: RenderPadding#00000\n'
' │ needsCompositing: false\n'
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
- ' │ Padding ← Container ← Align ← View-[GlobalObjectKey\n'
- ' │ TestWindow#00000] ← [root]\n'
+ ' │ Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
+ ' │ ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ layer: null\n'
@@ -403,8 +414,9 @@
' └─child: RenderPositionedBox#00000\n'
' │ needsCompositing: false\n'
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
- ' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+ ' │ TestWindow#00000] ← ⋯\n'
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
' │ layer: null\n'
@@ -420,8 +432,8 @@
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
' │ needsCompositing: false\n'
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
- ' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← ⋯\n'
' │ parentData: offset=Offset(14.0, 31.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
' │ layer: null\n'
@@ -435,7 +447,7 @@
' needsCompositing: false\n'
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
- ' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' MediaQuery ← _MediaQueryFromView ← ⋯\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
' layer: null\n'
@@ -452,8 +464,8 @@
' gradient: null\n'
' shape: rectangle\n'
' configuration: ImageConfiguration(bundle:\n'
- ' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
- ' android)\n'
+ ' PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
+ ' android)\n',
),
);
diff --git a/packages/flutter/test/widgets/custom_multi_child_layout_test.dart b/packages/flutter/test/widgets/custom_multi_child_layout_test.dart
index 5fd8c04..732ae02 100644
--- a/packages/flutter/test/widgets/custom_multi_child_layout_test.dart
+++ b/packages/flutter/test/widgets/custom_multi_child_layout_test.dart
@@ -372,7 +372,8 @@
' in its parent data.\n'
' The following child has no ID: RenderConstrainedBox#00000 NEEDS-LAYOUT NEEDS-PAINT:\n'
' creator: ConstrainedBox ← Container ← LayoutWithMissingId ←\n'
- ' CustomMultiChildLayout ← Center ← View-[GlobalObjectKey\n'
+ ' CustomMultiChildLayout ← Center ← MediaQuery ←\n'
+ ' _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
' TestWindow#00000] ← [root]\n'
' parentData: offset=Offset(0.0, 0.0); id=null\n'
' constraints: MISSING\n'
diff --git a/packages/flutter/test/widgets/debug_test.dart b/packages/flutter/test/widgets/debug_test.dart
index 30e2329..ee38464 100644
--- a/packages/flutter/test/widgets/debug_test.dart
+++ b/packages/flutter/test/widgets/debug_test.dart
@@ -96,8 +96,11 @@
});
testWidgets('debugCheckHasMediaQuery control test', (WidgetTester tester) async {
- await tester.pumpWidget(
- Builder(
+ // Cannot use tester.pumpWidget here because it wraps the widget in a View,
+ // which introduces a MediaQuery ancestor.
+ await pumpWidgetWithoutViewWrapper(
+ tester: tester,
+ widget: Builder(
builder: (BuildContext context) {
late FlutterError error;
try {
@@ -339,3 +342,9 @@
expect(renderObject.debugLayer?.debugCreator, isNotNull);
});
}
+
+Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, required Widget widget}) {
+ tester.binding.attachRootWidget(widget);
+ tester.binding.scheduleFrame();
+ return tester.binding.pump();
+}
diff --git a/packages/flutter/test/widgets/focus_manager_test.dart b/packages/flutter/test/widgets/focus_manager_test.dart
index dd36f86..53501fc 100644
--- a/packages/flutter/test/widgets/focus_manager_test.dart
+++ b/packages/flutter/test/widgets/focus_manager_test.dart
@@ -1228,8 +1228,9 @@
equalsIgnoringHashCodes(
'FocusManager#00000\n'
' │ primaryFocus: FocusNode#00000(Child 4 [PRIMARY FOCUS])\n'
- ' │ primaryFocusCreator: Container-[GlobalKey#00000] ←\n'
- ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ primaryFocusCreator: Container-[GlobalKey#00000] ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+ ' │ TestWindow#00000] ← [root]\n'
' │\n'
' └─rootScope: FocusScopeNode#00000(Root Focus Scope [IN FOCUS PATH])\n'
' │ IN FOCUS PATH\n'
diff --git a/packages/flutter/test/widgets/init_state_test.dart b/packages/flutter/test/widgets/init_state_test.dart
index 828893d..e70267e 100644
--- a/packages/flutter/test/widgets/init_state_test.dart
+++ b/packages/flutter/test/widgets/init_state_test.dart
@@ -30,7 +30,7 @@
void main() {
testWidgets('initState() is called when we are in the tree', (WidgetTester tester) async {
await tester.pumpWidget(const Parent(child: TestWidget()));
- expect(ancestors, equals(<String>['Parent', 'View', 'RenderObjectToWidgetAdapter<RenderBox>']));
+ expect(ancestors, containsAllInOrder(<String>['Parent', 'View', 'RenderObjectToWidgetAdapter<RenderBox>']));
});
}
diff --git a/packages/flutter/test/widgets/keep_alive_test.dart b/packages/flutter/test/widgets/keep_alive_test.dart
index 5249f5c..3b5f9e6 100644
--- a/packages/flutter/test/widgets/keep_alive_test.dart
+++ b/packages/flutter/test/widgets/keep_alive_test.dart
@@ -303,7 +303,7 @@
' │ ScrollDirection.idle)\n'
' │ anchor: 0.0\n'
' │\n'
- ' └─center child: RenderSliverFixedExtentList#00000 relayoutBoundary=up1\n'
+ ' └─center child: RenderSliverPadding#00000 relayoutBoundary=up1\n'
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: SliverConstraints(AxisDirection.down,\n'
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
@@ -314,49 +314,63 @@
' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
' │ cacheExtent: 850.0)\n'
- ' │ currently live children: 0 to 2\n'
+ ' │ padding: EdgeInsets.zero\n'
+ ' │ textDirection: ltr\n'
' │\n'
- ' ├─child with index 0: RenderLimitedBox#00000\n'
- ' │ │ parentData: index=0; layoutOffset=0.0\n'
- ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ │ size: Size(800.0, 400.0)\n'
- ' │ │ maxWidth: 400.0\n'
- ' │ │ maxHeight: 400.0\n'
- ' │ │\n'
- ' │ └─child: RenderCustomPaint#00000\n'
- ' │ parentData: <none> (can use size)\n'
- ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ size: Size(800.0, 400.0)\n'
- ' │ painter: _PlaceholderPainter#00000()\n'
- ' │ preferredSize: Size(Infinity, Infinity)\n'
- ' │\n'
- ' ├─child with index 1: RenderLimitedBox#00000\n' // <----- no dashed line starts here
- ' │ │ parentData: index=1; layoutOffset=400.0\n'
- ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ │ size: Size(800.0, 400.0)\n'
- ' │ │ maxWidth: 400.0\n'
- ' │ │ maxHeight: 400.0\n'
- ' │ │\n'
- ' │ └─child: RenderCustomPaint#00000\n'
- ' │ parentData: <none> (can use size)\n'
- ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ size: Size(800.0, 400.0)\n'
- ' │ painter: _PlaceholderPainter#00000()\n'
- ' │ preferredSize: Size(Infinity, Infinity)\n'
- ' │\n'
- ' └─child with index 2: RenderLimitedBox#00000 NEEDS-PAINT\n'
- ' │ parentData: index=2; layoutOffset=800.0\n'
- ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ size: Size(800.0, 400.0)\n'
- ' │ maxWidth: 400.0\n'
- ' │ maxHeight: 400.0\n'
+ ' └─child: RenderSliverFixedExtentList#00000 relayoutBoundary=up2\n'
+ ' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
+ ' │ constraints: SliverConstraints(AxisDirection.down,\n'
+ ' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
+ ' │ 0.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n'
+ ' │ crossAxisDirection: AxisDirection.right,\n'
+ ' │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 850.0,\n'
+ ' │ cacheOrigin: 0.0)\n'
+ ' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
+ ' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
+ ' │ cacheExtent: 850.0)\n'
+ ' │ currently live children: 0 to 2\n'
' │\n'
- ' └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
- ' parentData: <none> (can use size)\n'
- ' constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' size: Size(800.0, 400.0)\n'
- ' painter: _PlaceholderPainter#00000()\n'
- ' preferredSize: Size(Infinity, Infinity)\n',
+ ' ├─child with index 0: RenderLimitedBox#00000\n'
+ ' │ │ parentData: index=0; layoutOffset=0.0\n'
+ ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ │ size: Size(800.0, 400.0)\n'
+ ' │ │ maxWidth: 400.0\n'
+ ' │ │ maxHeight: 400.0\n'
+ ' │ │\n'
+ ' │ └─child: RenderCustomPaint#00000\n'
+ ' │ parentData: <none> (can use size)\n'
+ ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ size: Size(800.0, 400.0)\n'
+ ' │ painter: _PlaceholderPainter#00000()\n'
+ ' │ preferredSize: Size(Infinity, Infinity)\n'
+ ' │\n'
+ ' ├─child with index 1: RenderLimitedBox#00000\n' // <----- no dashed line starts here
+ ' │ │ parentData: index=1; layoutOffset=400.0\n'
+ ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ │ size: Size(800.0, 400.0)\n'
+ ' │ │ maxWidth: 400.0\n'
+ ' │ │ maxHeight: 400.0\n'
+ ' │ │\n'
+ ' │ └─child: RenderCustomPaint#00000\n'
+ ' │ parentData: <none> (can use size)\n'
+ ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ size: Size(800.0, 400.0)\n'
+ ' │ painter: _PlaceholderPainter#00000()\n'
+ ' │ preferredSize: Size(Infinity, Infinity)\n'
+ ' │\n'
+ ' └─child with index 2: RenderLimitedBox#00000 NEEDS-PAINT\n'
+ ' │ parentData: index=2; layoutOffset=800.0\n'
+ ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ size: Size(800.0, 400.0)\n'
+ ' │ maxWidth: 400.0\n'
+ ' │ maxHeight: 400.0\n'
+ ' │\n'
+ ' └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
+ ' parentData: <none> (can use size)\n'
+ ' constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' size: Size(800.0, 400.0)\n'
+ ' painter: _PlaceholderPainter#00000()\n'
+ ' preferredSize: Size(Infinity, Infinity)\n',
));
const GlobalObjectKey<_LeafState>(0).currentState!.setKeepAlive(true);
await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0));
@@ -463,7 +477,7 @@
' │ ScrollDirection.idle)\n'
' │ anchor: 0.0\n'
' │\n'
- ' └─center child: RenderSliverFixedExtentList#00000 relayoutBoundary=up1\n'
+ ' └─center child: RenderSliverPadding#00000 relayoutBoundary=up1\n'
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: SliverConstraints(AxisDirection.down,\n'
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
@@ -474,92 +488,105 @@
' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
' │ cacheExtent: 1100.0)\n'
- ' │ currently live children: 4 to 7\n'
+ ' │ padding: EdgeInsets.zero\n'
+ ' │ textDirection: ltr\n'
' │\n'
- ' ├─child with index 4: RenderLimitedBox#00000 NEEDS-PAINT\n'
- ' │ │ parentData: index=4; layoutOffset=1600.0\n'
- ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ │ size: Size(800.0, 400.0)\n'
- ' │ │ maxWidth: 400.0\n'
- ' │ │ maxHeight: 400.0\n'
- ' │ │\n'
- ' │ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
- ' │ parentData: <none> (can use size)\n'
- ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ size: Size(800.0, 400.0)\n'
- ' │ painter: _PlaceholderPainter#00000()\n'
- ' │ preferredSize: Size(Infinity, Infinity)\n'
- ' │\n'
- ' ├─child with index 5: RenderLimitedBox#00000\n' // <----- this is index 5, not 0
- ' │ │ parentData: index=5; layoutOffset=2000.0\n'
- ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ │ size: Size(800.0, 400.0)\n'
- ' │ │ maxWidth: 400.0\n'
- ' │ │ maxHeight: 400.0\n'
- ' │ │\n'
- ' │ └─child: RenderCustomPaint#00000\n'
- ' │ parentData: <none> (can use size)\n'
- ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ size: Size(800.0, 400.0)\n'
- ' │ painter: _PlaceholderPainter#00000()\n'
- ' │ preferredSize: Size(Infinity, Infinity)\n'
- ' │\n'
- ' ├─child with index 6: RenderLimitedBox#00000\n'
- ' │ │ parentData: index=6; layoutOffset=2400.0\n'
- ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ │ size: Size(800.0, 400.0)\n'
- ' │ │ maxWidth: 400.0\n'
- ' │ │ maxHeight: 400.0\n'
- ' │ │\n'
- ' │ └─child: RenderCustomPaint#00000\n'
- ' │ parentData: <none> (can use size)\n'
- ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ size: Size(800.0, 400.0)\n'
- ' │ painter: _PlaceholderPainter#00000()\n'
- ' │ preferredSize: Size(Infinity, Infinity)\n'
- ' │\n'
- ' ├─child with index 7: RenderLimitedBox#00000 NEEDS-PAINT\n'
- ' ╎ │ parentData: index=7; layoutOffset=2800.0\n'
- ' ╎ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' ╎ │ size: Size(800.0, 400.0)\n'
- ' ╎ │ maxWidth: 400.0\n'
- ' ╎ │ maxHeight: 400.0\n'
- ' ╎ │\n'
- ' ╎ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
- ' ╎ parentData: <none> (can use size)\n'
- ' ╎ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' ╎ size: Size(800.0, 400.0)\n'
- ' ╎ painter: _PlaceholderPainter#00000()\n'
- ' ╎ preferredSize: Size(Infinity, Infinity)\n'
- ' ╎\n'
- ' ╎╌child with index 0 (kept alive but not laid out): RenderLimitedBox#00000\n' // <----- this one is index 0 and is marked as being kept alive but not laid out
- ' ╎ │ parentData: index=0; keepAlive; layoutOffset=0.0\n'
- ' ╎ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' ╎ │ size: Size(800.0, 400.0)\n'
- ' ╎ │ maxWidth: 400.0\n'
- ' ╎ │ maxHeight: 400.0\n'
- ' ╎ │\n'
- ' ╎ └─child: RenderCustomPaint#00000\n'
- ' ╎ parentData: <none> (can use size)\n'
- ' ╎ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' ╎ size: Size(800.0, 400.0)\n'
- ' ╎ painter: _PlaceholderPainter#00000()\n'
- ' ╎ preferredSize: Size(Infinity, Infinity)\n'
- ' ╎\n' // <----- dashed line ends here
- ' └╌child with index 3 (kept alive but not laid out): RenderLimitedBox#00000\n'
- ' │ parentData: index=3; keepAlive; layoutOffset=1200.0\n'
- ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' │ size: Size(800.0, 400.0)\n'
- ' │ maxWidth: 400.0\n'
- ' │ maxHeight: 400.0\n'
+ ' └─child: RenderSliverFixedExtentList#00000 relayoutBoundary=up2\n'
+ ' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
+ ' │ constraints: SliverConstraints(AxisDirection.down,\n'
+ ' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
+ ' │ 2000.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n'
+ ' │ crossAxisDirection: AxisDirection.right,\n'
+ ' │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 1100.0,\n'
+ ' │ cacheOrigin: -250.0)\n'
+ ' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
+ ' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
+ ' │ cacheExtent: 1100.0)\n'
+ ' │ currently live children: 4 to 7\n'
' │\n'
- ' └─child: RenderCustomPaint#00000\n'
- ' parentData: <none> (can use size)\n'
- ' constraints: BoxConstraints(w=800.0, h=400.0)\n'
- ' size: Size(800.0, 400.0)\n'
- ' painter: _PlaceholderPainter#00000()\n'
- ' preferredSize: Size(Infinity, Infinity)\n',
+ ' ├─child with index 4: RenderLimitedBox#00000 NEEDS-PAINT\n'
+ ' │ │ parentData: index=4; layoutOffset=1600.0\n'
+ ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ │ size: Size(800.0, 400.0)\n'
+ ' │ │ maxWidth: 400.0\n'
+ ' │ │ maxHeight: 400.0\n'
+ ' │ │\n'
+ ' │ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
+ ' │ parentData: <none> (can use size)\n'
+ ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ size: Size(800.0, 400.0)\n'
+ ' │ painter: _PlaceholderPainter#00000()\n'
+ ' │ preferredSize: Size(Infinity, Infinity)\n'
+ ' │\n'
+ ' ├─child with index 5: RenderLimitedBox#00000\n' // <----- this is index 5, not 0
+ ' │ │ parentData: index=5; layoutOffset=2000.0\n'
+ ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ │ size: Size(800.0, 400.0)\n'
+ ' │ │ maxWidth: 400.0\n'
+ ' │ │ maxHeight: 400.0\n'
+ ' │ │\n'
+ ' │ └─child: RenderCustomPaint#00000\n'
+ ' │ parentData: <none> (can use size)\n'
+ ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ size: Size(800.0, 400.0)\n'
+ ' │ painter: _PlaceholderPainter#00000()\n'
+ ' │ preferredSize: Size(Infinity, Infinity)\n'
+ ' │\n'
+ ' ├─child with index 6: RenderLimitedBox#00000\n'
+ ' │ │ parentData: index=6; layoutOffset=2400.0\n'
+ ' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ │ size: Size(800.0, 400.0)\n'
+ ' │ │ maxWidth: 400.0\n'
+ ' │ │ maxHeight: 400.0\n'
+ ' │ │\n'
+ ' │ └─child: RenderCustomPaint#00000\n'
+ ' │ parentData: <none> (can use size)\n'
+ ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ size: Size(800.0, 400.0)\n'
+ ' │ painter: _PlaceholderPainter#00000()\n'
+ ' │ preferredSize: Size(Infinity, Infinity)\n'
+ ' │\n'
+ ' ├─child with index 7: RenderLimitedBox#00000 NEEDS-PAINT\n'
+ ' ╎ │ parentData: index=7; layoutOffset=2800.0\n'
+ ' ╎ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' ╎ │ size: Size(800.0, 400.0)\n'
+ ' ╎ │ maxWidth: 400.0\n'
+ ' ╎ │ maxHeight: 400.0\n'
+ ' ╎ │\n'
+ ' ╎ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
+ ' ╎ parentData: <none> (can use size)\n'
+ ' ╎ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' ╎ size: Size(800.0, 400.0)\n'
+ ' ╎ painter: _PlaceholderPainter#00000()\n'
+ ' ╎ preferredSize: Size(Infinity, Infinity)\n'
+ ' ╎\n'
+ ' ╎╌child with index 0 (kept alive but not laid out): RenderLimitedBox#00000\n' // <----- this one is index 0 and is marked as being kept alive but not laid out
+ ' ╎ │ parentData: index=0; keepAlive; layoutOffset=0.0\n'
+ ' ╎ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' ╎ │ size: Size(800.0, 400.0)\n'
+ ' ╎ │ maxWidth: 400.0\n'
+ ' ╎ │ maxHeight: 400.0\n'
+ ' ╎ │\n'
+ ' ╎ └─child: RenderCustomPaint#00000\n'
+ ' ╎ parentData: <none> (can use size)\n'
+ ' ╎ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' ╎ size: Size(800.0, 400.0)\n'
+ ' ╎ painter: _PlaceholderPainter#00000()\n'
+ ' ╎ preferredSize: Size(Infinity, Infinity)\n'
+ ' ╎\n'
+ ' └╌child with index 3 (kept alive but not laid out): RenderLimitedBox#00000\n'
+ ' │ parentData: index=3; keepAlive; layoutOffset=1200.0\n'
+ ' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' │ size: Size(800.0, 400.0)\n'
+ ' │ maxWidth: 400.0\n'
+ ' │ maxHeight: 400.0\n'
+ ' │\n'
+ ' └─child: RenderCustomPaint#00000\n'
+ ' parentData: <none> (can use size)\n'
+ ' constraints: BoxConstraints(w=800.0, h=400.0)\n'
+ ' size: Size(800.0, 400.0)\n'
+ ' painter: _PlaceholderPainter#00000()\n'
+ ' preferredSize: Size(Infinity, Infinity)\n',
));
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87876
-
}
diff --git a/packages/flutter/test/widgets/list_view_viewporting_test.dart b/packages/flutter/test/widgets/list_view_viewporting_test.dart
index 11a7906..277b20e 100644
--- a/packages/flutter/test/widgets/list_view_viewporting_test.dart
+++ b/packages/flutter/test/widgets/list_view_viewporting_test.dart
@@ -326,7 +326,7 @@
expect(
list.toStringDeep(minLevel: DiagnosticLevel.info),
equalsIgnoringHashCodes(
- 'RenderSliverList#00000 relayoutBoundary=up1\n'
+ 'RenderSliverList#00000 relayoutBoundary=up2\n'
' │ needs compositing\n'
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: SliverConstraints(AxisDirection.down,\n'
@@ -339,7 +339,7 @@
' │ maxPaintExtent: 300.0, cacheExtent: 300.0)\n'
' │ currently live children: 0 to 2\n'
' │\n'
- ' ├─child with index 0: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
+ ' ├─child with index 0: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
' │ │ needs compositing\n'
' │ │ parentData: index=0; layoutOffset=0.0 (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
@@ -349,7 +349,7 @@
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ │ repaints)\n'
' │ │\n'
- ' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
+ ' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
' │ │ parentData: <none> (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ │ size: Size(800.0, 100.0)\n'
@@ -368,7 +368,7 @@
' │ size: Size(800.0, 100.0)\n'
' │ additionalConstraints: BoxConstraints(biggest)\n'
' │\n'
- ' ├─child with index 1: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
+ ' ├─child with index 1: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
' │ │ needs compositing\n'
' │ │ parentData: index=1; layoutOffset=100.0 (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
@@ -378,7 +378,7 @@
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ │ repaints)\n'
' │ │\n'
- ' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
+ ' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
' │ │ parentData: <none> (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ │ size: Size(800.0, 100.0)\n'
@@ -397,7 +397,7 @@
' │ size: Size(800.0, 100.0)\n'
' │ additionalConstraints: BoxConstraints(biggest)\n'
' │\n'
- ' └─child with index 2: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
+ ' └─child with index 2: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
' │ needs compositing\n'
' │ parentData: index=2; layoutOffset=200.0 (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
@@ -407,7 +407,7 @@
' │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ repaints)\n'
' │\n'
- ' └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
+ ' └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ size: Size(800.0, 100.0)\n'
diff --git a/packages/flutter/test/widgets/media_query_test.dart b/packages/flutter/test/widgets/media_query_test.dart
index 0dea109..5cecc50 100644
--- a/packages/flutter/test/widgets/media_query_test.dart
+++ b/packages/flutter/test/widgets/media_query_test.dart
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:ui' show Brightness, DisplayFeature, DisplayFeatureState, DisplayFeatureType, GestureSettings, ViewConfiguration;
+import 'dart:ui' show Brightness, DisplayFeature, DisplayFeatureState, DisplayFeatureType, GestureSettings, PlatformDispatcher, ViewConfiguration, WindowPadding;
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
@@ -45,8 +45,11 @@
void main() {
testWidgets('MediaQuery does not have a default', (WidgetTester tester) async {
bool tested = false;
- await tester.pumpWidget(
- Builder(
+ // Cannot use tester.pumpWidget here because it wraps the widget in a View,
+ // which introduces a MediaQuery ancestor.
+ await pumpWidgetWithoutViewWrapper(
+ tester: tester,
+ widget: Builder(
builder: (BuildContext context) {
tested = true;
MediaQuery.of(context); // should throw
@@ -108,8 +111,11 @@
testWidgets('MediaQuery.maybeOf defaults to null', (WidgetTester tester) async {
bool tested = false;
- await tester.pumpWidget(
- Builder(
+ // Cannot use tester.pumpWidget here because it wraps the widget in a View,
+ // which introduces a MediaQuery ancestor.
+ await pumpWidgetWithoutViewWrapper(
+ tester: tester,
+ widget: Builder(
builder: (BuildContext context) {
final MediaQueryData? data = MediaQuery.maybeOf(context);
expect(data, isNull);
@@ -154,6 +160,358 @@
expect(data.displayFeatures, isEmpty);
});
+ testWidgets('MediaQueryData.fromView uses platformData if provided', (WidgetTester tester) async {
+ const MediaQueryData platformData = MediaQueryData(
+ textScaleFactor: 1234,
+ platformBrightness: Brightness.dark,
+ accessibleNavigation: true,
+ invertColors: true,
+ disableAnimations: true,
+ boldText: true,
+ highContrast: true,
+ alwaysUse24HourFormat: true,
+ navigationMode: NavigationMode.directional,
+ );
+
+ final TestView view = TestView(
+ physicalSize: const Size(300, 600),
+ devicePixelRatio: 3.0,
+ padding: const TestWindowPadding(15),
+ viewPadding: const TestWindowPadding(75),
+ viewInsets: const TestWindowPadding(45),
+ systemGestureInsets: const TestWindowPadding(9),
+ );
+
+ final MediaQueryData data = MediaQueryData.fromView(view, platformData: platformData);
+ expect(data, hasOneLineDescription);
+ expect(data.hashCode, data.copyWith().hashCode);
+ expect(data.size, view.physicalSize / view.devicePixelRatio);
+ expect(data.devicePixelRatio, view.devicePixelRatio);
+ expect(data.textScaleFactor, platformData.textScaleFactor);
+ expect(data.platformBrightness, platformData.platformBrightness);
+ expect(data.padding, EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio));
+ expect(data.viewPadding, EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio));
+ expect(data.viewInsets, EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio));
+ expect(data.systemGestureInsets, EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio));
+ expect(data.accessibleNavigation, platformData.accessibleNavigation);
+ expect(data.invertColors, platformData.invertColors);
+ expect(data.disableAnimations, platformData.disableAnimations);
+ expect(data.boldText, platformData.boldText);
+ expect(data.highContrast, platformData.highContrast);
+ expect(data.alwaysUse24HourFormat, platformData.alwaysUse24HourFormat);
+ expect(data.navigationMode, platformData.navigationMode);
+ expect(data.gestureSettings, DeviceGestureSettings.fromWindow(view));
+ expect(data.displayFeatures, view.displayFeatures);
+ });
+
+ testWidgets('MediaQueryData.fromView uses data from platformDispatcher if no platformData is provided', (WidgetTester tester) async {
+ final TestPlatformDispatcher platformDispatcher = TestPlatformDispatcher(platformDispatcher: tester.binding.platformDispatcher);
+ platformDispatcher
+ ..textScaleFactorTestValue = 123
+ ..platformBrightnessTestValue = Brightness.dark
+ ..accessibilityFeaturesTestValue = FakeAccessibilityFeatures.allOn;
+ addTearDown(() => platformDispatcher.clearAllTestValues());
+
+ final TestView view = TestView(
+ platformDispatcher: platformDispatcher,
+ physicalSize: const Size(300, 600),
+ devicePixelRatio: 3.0,
+ padding: const TestWindowPadding(15),
+ viewPadding: const TestWindowPadding(75),
+ viewInsets: const TestWindowPadding(45),
+ systemGestureInsets: const TestWindowPadding(9),
+ );
+
+ final MediaQueryData data = MediaQueryData.fromView(view);
+ expect(data, hasOneLineDescription);
+ expect(data.hashCode, data.copyWith().hashCode);
+ expect(data.size, view.physicalSize / view.devicePixelRatio);
+ expect(data.devicePixelRatio, view.devicePixelRatio);
+ expect(data.textScaleFactor, platformDispatcher.textScaleFactor);
+ expect(data.platformBrightness, platformDispatcher.platformBrightness);
+ expect(data.padding, EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio));
+ expect(data.viewPadding, EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio));
+ expect(data.viewInsets, EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio));
+ expect(data.systemGestureInsets, EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio));
+ expect(data.accessibleNavigation, platformDispatcher.accessibilityFeatures.accessibleNavigation);
+ expect(data.invertColors, platformDispatcher.accessibilityFeatures.invertColors);
+ expect(data.disableAnimations, platformDispatcher.accessibilityFeatures.disableAnimations);
+ expect(data.boldText, platformDispatcher.accessibilityFeatures.boldText);
+ expect(data.highContrast, platformDispatcher.accessibilityFeatures.highContrast);
+ expect(data.alwaysUse24HourFormat, platformDispatcher.alwaysUse24HourFormat);
+ expect(data.navigationMode, NavigationMode.traditional);
+ expect(data.gestureSettings, DeviceGestureSettings.fromWindow(view));
+ expect(data.displayFeatures, view.displayFeatures);
+ });
+
+ testWidgets('MediaQuery.fromView injects a new MediaQuery with data from view, preserving platform-specific data', (WidgetTester tester) async {
+ const MediaQueryData platformData = MediaQueryData(
+ textScaleFactor: 1234,
+ platformBrightness: Brightness.dark,
+ accessibleNavigation: true,
+ invertColors: true,
+ disableAnimations: true,
+ boldText: true,
+ highContrast: true,
+ alwaysUse24HourFormat: true,
+ navigationMode: NavigationMode.directional,
+ );
+
+ final TestView view = TestView(
+ physicalSize: const Size(300, 600),
+ devicePixelRatio: 3.0,
+ padding: const TestWindowPadding(15),
+ viewPadding: const TestWindowPadding(75),
+ viewInsets: const TestWindowPadding(45),
+ systemGestureInsets: const TestWindowPadding(9),
+ );
+
+ late MediaQueryData data;
+ await tester.pumpWidget(MediaQuery(
+ data: platformData,
+ child: MediaQuery.fromView(
+ view: view,
+ child: Builder(
+ builder: (BuildContext context) {
+ data = MediaQuery.of(context);
+ return const Placeholder();
+ },
+ )
+ )
+ ));
+
+ expect(data, isNot(platformData));
+ expect(data.size, view.physicalSize / view.devicePixelRatio);
+ expect(data.devicePixelRatio, view.devicePixelRatio);
+ expect(data.textScaleFactor, platformData.textScaleFactor);
+ expect(data.platformBrightness, platformData.platformBrightness);
+ expect(data.padding, EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio));
+ expect(data.viewPadding, EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio));
+ expect(data.viewInsets, EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio));
+ expect(data.systemGestureInsets, EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio));
+ expect(data.accessibleNavigation, platformData.accessibleNavigation);
+ expect(data.invertColors, platformData.invertColors);
+ expect(data.disableAnimations, platformData.disableAnimations);
+ expect(data.boldText, platformData.boldText);
+ expect(data.highContrast, platformData.highContrast);
+ expect(data.alwaysUse24HourFormat, platformData.alwaysUse24HourFormat);
+ expect(data.navigationMode, platformData.navigationMode);
+ expect(data.gestureSettings, DeviceGestureSettings.fromWindow(view));
+ expect(data.displayFeatures, view.displayFeatures);
+ });
+
+ testWidgets('MediaQuery.fromView injects a new MediaQuery with data from view when no sourrounding MediaQuery exists', (WidgetTester tester) async {
+ final TestPlatformDispatcher platformDispatcher = TestPlatformDispatcher(platformDispatcher: tester.binding.platformDispatcher);
+ platformDispatcher
+ ..textScaleFactorTestValue = 123
+ ..platformBrightnessTestValue = Brightness.dark
+ ..accessibilityFeaturesTestValue = FakeAccessibilityFeatures.allOn;
+ addTearDown(() => platformDispatcher.clearAllTestValues());
+
+ final TestView view = TestView(
+ platformDispatcher: platformDispatcher,
+ physicalSize: const Size(300, 600),
+ devicePixelRatio: 3.0,
+ padding: const TestWindowPadding(15),
+ viewPadding: const TestWindowPadding(75),
+ viewInsets: const TestWindowPadding(45),
+ systemGestureInsets: const TestWindowPadding(9),
+ );
+
+ late MediaQueryData data;
+ MediaQueryData? outerData;
+ await pumpWidgetWithoutViewWrapper(
+ tester: tester,
+ widget: Builder(
+ builder: (BuildContext context) {
+ outerData = MediaQuery.maybeOf(context);
+ return MediaQuery.fromView(
+ view: view,
+ child: Builder(
+ builder: (BuildContext context) {
+ data = MediaQuery.of(context);
+ return const Placeholder();
+ },
+ )
+ );
+ },
+ ),
+ );
+
+ expect(outerData, isNull);
+ expect(data.size, view.physicalSize / view.devicePixelRatio);
+ expect(data.devicePixelRatio, view.devicePixelRatio);
+ expect(data.textScaleFactor, platformDispatcher.textScaleFactor);
+ expect(data.platformBrightness, platformDispatcher.platformBrightness);
+ expect(data.padding, EdgeInsets.fromWindowPadding(view.padding, view.devicePixelRatio));
+ expect(data.viewPadding, EdgeInsets.fromWindowPadding(view.viewPadding, view.devicePixelRatio));
+ expect(data.viewInsets, EdgeInsets.fromWindowPadding(view.viewInsets, view.devicePixelRatio));
+ expect(data.systemGestureInsets, EdgeInsets.fromWindowPadding(view.systemGestureInsets, view.devicePixelRatio));
+ expect(data.accessibleNavigation, platformDispatcher.accessibilityFeatures.accessibleNavigation);
+ expect(data.invertColors, platformDispatcher.accessibilityFeatures.invertColors);
+ expect(data.disableAnimations, platformDispatcher.accessibilityFeatures.disableAnimations);
+ expect(data.boldText, platformDispatcher.accessibilityFeatures.boldText);
+ expect(data.highContrast, platformDispatcher.accessibilityFeatures.highContrast);
+ expect(data.alwaysUse24HourFormat, platformDispatcher.alwaysUse24HourFormat);
+ expect(data.navigationMode, NavigationMode.traditional);
+ expect(data.gestureSettings, DeviceGestureSettings.fromWindow(view));
+ expect(data.displayFeatures, view.displayFeatures);
+ });
+
+ testWidgets('MediaQuery.fromView updates on notifications (no parent data)', (WidgetTester tester) async {
+ tester.binding.platformDispatcher
+ ..textScaleFactorTestValue = 123
+ ..platformBrightnessTestValue = Brightness.dark
+ ..accessibilityFeaturesTestValue = FakeAccessibilityFeatures.allOn;
+ addTearDown(() => tester.binding.platformDispatcher.clearAllTestValues());
+ tester.binding.window.devicePixelRatioTestValue = 44;
+ addTearDown(() => tester.binding.window.clearAllTestValues());
+
+ late MediaQueryData data;
+ MediaQueryData? outerData;
+ int rebuildCount = 0;
+ await pumpWidgetWithoutViewWrapper(
+ tester: tester,
+ widget: Builder(
+ builder: (BuildContext context) {
+ outerData = MediaQuery.maybeOf(context);
+ return MediaQuery.fromView(
+ view: tester.binding.window,
+ child: Builder(
+ builder: (BuildContext context) {
+ rebuildCount++;
+ data = MediaQuery.of(context);
+ return const Placeholder();
+ },
+ ),
+ );
+ },
+ ),
+ );
+
+ expect(outerData, isNull);
+ expect(rebuildCount, 1);
+
+ expect(data.textScaleFactor, 123);
+ tester.binding.platformDispatcher.textScaleFactorTestValue = 456;
+ await tester.pump();
+ expect(data.textScaleFactor, 456);
+ expect(rebuildCount, 2);
+
+ expect(data.platformBrightness, Brightness.dark);
+ tester.binding.platformDispatcher.platformBrightnessTestValue = Brightness.light;
+ await tester.pump();
+ expect(data.platformBrightness, Brightness.light);
+ expect(rebuildCount, 3);
+
+ expect(data.accessibleNavigation, true);
+ tester.binding.platformDispatcher.accessibilityFeaturesTestValue = const FakeAccessibilityFeatures();
+ await tester.pump();
+ expect(data.accessibleNavigation, false);
+ expect(rebuildCount, 4);
+
+ expect(data.devicePixelRatio, 44);
+ tester.binding.window.devicePixelRatioTestValue = 55;
+ await tester.pump();
+ expect(data.devicePixelRatio, 55);
+ expect(rebuildCount, 5);
+ });
+
+ testWidgets('MediaQuery.fromView updates on notifications (with parent data)', (WidgetTester tester) async {
+ tester.binding.platformDispatcher
+ ..textScaleFactorTestValue = 123
+ ..platformBrightnessTestValue = Brightness.dark
+ ..accessibilityFeaturesTestValue = FakeAccessibilityFeatures.allOn;
+ addTearDown(() => tester.binding.platformDispatcher.clearAllTestValues());
+ tester.binding.window.devicePixelRatioTestValue = 44;
+ addTearDown(() => tester.binding.window.clearAllTestValues());
+
+ late MediaQueryData data;
+ int rebuildCount = 0;
+ await tester.pumpWidget(
+ MediaQuery(
+ data: const MediaQueryData(
+ textScaleFactor: 44,
+ platformBrightness: Brightness.dark,
+ accessibleNavigation: true,
+ ),
+ child: MediaQuery.fromView(
+ view: tester.binding.window,
+ child: Builder(
+ builder: (BuildContext context) {
+ rebuildCount++;
+ data = MediaQuery.of(context);
+ return const Placeholder();
+ },
+ ),
+ ),
+ ),
+ );
+
+ expect(rebuildCount, 1);
+
+ expect(data.textScaleFactor, 44);
+ tester.binding.platformDispatcher.textScaleFactorTestValue = 456;
+ await tester.pump();
+ expect(data.textScaleFactor, 44);
+ expect(rebuildCount, 1);
+
+ expect(data.platformBrightness, Brightness.dark);
+ tester.binding.platformDispatcher.platformBrightnessTestValue = Brightness.light;
+ await tester.pump();
+ expect(data.platformBrightness, Brightness.dark);
+ expect(rebuildCount, 1);
+
+ expect(data.accessibleNavigation, true);
+ tester.binding.platformDispatcher.accessibilityFeaturesTestValue = const FakeAccessibilityFeatures();
+ await tester.pump();
+ expect(data.accessibleNavigation, true);
+ expect(rebuildCount, 1);
+
+ expect(data.devicePixelRatio, 44);
+ tester.binding.window.devicePixelRatioTestValue = 55;
+ await tester.pump();
+ expect(data.devicePixelRatio, 55);
+ expect(rebuildCount, 2);
+ });
+
+ testWidgets('MediaQuery.fromView updates when parent data changes', (WidgetTester tester) async {
+ late MediaQueryData data;
+ int rebuildCount = 0;
+ double textScaleFactor = 55;
+ late StateSetter stateSetter;
+ await tester.pumpWidget(
+ StatefulBuilder(
+ builder: (BuildContext context, StateSetter setState) {
+ stateSetter = setState;
+ return MediaQuery(
+ data: MediaQueryData(textScaleFactor: textScaleFactor),
+ child: MediaQuery.fromView(
+ view: tester.binding.window,
+ child: Builder(
+ builder: (BuildContext context) {
+ rebuildCount++;
+ data = MediaQuery.of(context);
+ return const Placeholder();
+ },
+ ),
+ ),
+ );
+ },
+ ),
+ );
+
+ expect(rebuildCount, 1);
+ expect(data.textScaleFactor, 55);
+
+ stateSetter(() {
+ textScaleFactor = 66;
+ });
+ await tester.pump();
+ expect(data.textScaleFactor, 66);
+ expect(rebuildCount, 2);
+ });
+
testWidgets('MediaQueryData.copyWith defaults to source', (WidgetTester tester) async {
final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
final MediaQueryData copied = data.copyWith();
@@ -753,19 +1111,17 @@
});
testWidgets('MediaQuery.fromWindow creates a MediaQuery', (WidgetTester tester) async {
- bool hasMediaQueryAsParentOutside = false;
- bool hasMediaQueryAsParentInside = false;
+ MediaQuery? mediaQueryOutside;
+ MediaQuery? mediaQueryInside;
await tester.pumpWidget(
Builder(
builder: (BuildContext context) {
- hasMediaQueryAsParentOutside =
- context.findAncestorWidgetOfExactType<MediaQuery>() != null;
+ mediaQueryOutside = context.findAncestorWidgetOfExactType<MediaQuery>();
return MediaQuery.fromWindow(
child: Builder(
builder: (BuildContext context) {
- hasMediaQueryAsParentInside =
- context.findAncestorWidgetOfExactType<MediaQuery>() != null;
+ mediaQueryInside = context.findAncestorWidgetOfExactType<MediaQuery>();
return const SizedBox();
},
),
@@ -774,8 +1130,8 @@
),
);
- expect(hasMediaQueryAsParentOutside, false);
- expect(hasMediaQueryAsParentInside, true);
+ expect(mediaQueryInside, isNotNull);
+ expect(mediaQueryOutside, isNot(mediaQueryInside));
});
testWidgets('MediaQueryData.fromWindow is created using window values', (WidgetTester tester) async {
@@ -1150,3 +1506,58 @@
]
));
}
+
+Future<void> pumpWidgetWithoutViewWrapper({required WidgetTester tester, required Widget widget}) {
+ tester.binding.attachRootWidget(widget);
+ tester.binding.scheduleFrame();
+ return tester.binding.pump();
+}
+
+class TestView implements FlutterView {
+ TestView({
+ PlatformDispatcher? platformDispatcher,
+ required this.physicalSize,
+ required this.devicePixelRatio,
+ required this.padding,
+ required this.viewPadding,
+ required this.viewInsets,
+ required this.systemGestureInsets,
+ }) : _platformDispatcher = platformDispatcher;
+
+ @override
+ PlatformDispatcher get platformDispatcher => _platformDispatcher!;
+ final PlatformDispatcher? _platformDispatcher;
+ @override
+ final Size physicalSize;
+ @override
+ final double devicePixelRatio;
+ @override
+ final WindowPadding padding;
+ @override
+ final WindowPadding viewPadding;
+ @override
+ final WindowPadding viewInsets;
+ @override
+ final WindowPadding systemGestureInsets;
+ @override
+ final ViewConfiguration viewConfiguration = const ViewConfiguration();
+ @override
+ final List<DisplayFeature> displayFeatures = <DisplayFeature>[];
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class TestWindowPadding implements WindowPadding {
+ const TestWindowPadding(this.value);
+ final double value;
+
+ @override
+ double get bottom => value;
+ @override
+ double get left => value;
+ @override
+ double get right => value;
+ @override
+ double get top => value;
+}
diff --git a/packages/flutter/test/widgets/selectable_text_test.dart b/packages/flutter/test/widgets/selectable_text_test.dart
index a3cc298..a1fdd05 100644
--- a/packages/flutter/test/widgets/selectable_text_test.dart
+++ b/packages/flutter/test/widgets/selectable_text_test.dart
@@ -2707,14 +2707,6 @@
semantics.dispose();
});
- testWidgets('SelectableText throws when not descended from a MediaQuery widget', (WidgetTester tester) async {
- const Widget selectableText = SelectableText('something');
- await tester.pumpWidget(selectableText);
- final dynamic exception = tester.takeException();
- expect(exception, isFlutterError);
- expect(exception.toString(), startsWith('No MediaQuery widget ancestor found.\nSelectableText widgets require a MediaQuery widget ancestor.'));
- });
-
testWidgets('onTap is called upon tap', (WidgetTester tester) async {
int tapCount = 0;
await tester.pumpWidget(
diff --git a/packages/flutter/test/widgets/slotted_render_object_widget_test.dart b/packages/flutter/test/widgets/slotted_render_object_widget_test.dart
index 257951a..b8816d7 100644
--- a/packages/flutter/test/widgets/slotted_render_object_widget_test.dart
+++ b/packages/flutter/test/widgets/slotted_render_object_widget_test.dart
@@ -221,14 +221,16 @@
tester.renderObject(find.byType(_Diagonal)).toStringDeep(),
equalsIgnoringHashCodes(
'_RenderDiagonal#00000 relayoutBoundary=up1\n'
- ' │ creator: _Diagonal ← Align ← Directionality ←\n'
- ' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
+ ' │ creator: _Diagonal ← Align ← Directionality ← MediaQuery ←\n'
+ ' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
+ ' │ TestWindow#00000] ← [root]\n'
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
' │ size: Size(190.0, 220.0)\n'
' │\n'
' ├─topLeft: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
' │ creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
+ ' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: BoxConstraints(unconstrained)\n'
@@ -237,6 +239,7 @@
' │\n'
' └─bottomRight: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
' creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
+ ' MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
' parentData: offset=Offset(80.0, 100.0) (can use size)\n'
' constraints: BoxConstraints(unconstrained)\n'
diff --git a/packages/flutter/test/widgets/table_test.dart b/packages/flutter/test/widgets/table_test.dart
index 345c941..ea9fc30 100644
--- a/packages/flutter/test/widgets/table_test.dart
+++ b/packages/flutter/test/widgets/table_test.dart
@@ -879,24 +879,24 @@
expect(
element.toStringDeep(minLevel: DiagnosticLevel.info),
equalsIgnoringHashCodes(
- 'Table-[GlobalKey#00000](dependencies: [Directionality], renderObject: RenderTable#00000)\n'
- '├Text("A")\n'
+ 'Table-[GlobalKey#00000](dependencies: [Directionality, MediaQuery], renderObject: RenderTable#00000)\n'
+ '├Text("A", dependencies: [MediaQuery])\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "A", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
- '├Text("B")\n'
+ '├Text("B", dependencies: [MediaQuery])\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "B", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
- '├Text("C")\n'
+ '├Text("C", dependencies: [MediaQuery])\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "C", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
- '├Text("D")\n'
+ '├Text("D", dependencies: [MediaQuery])\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "D", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
- '├Text("EEE")\n'
+ '├Text("EEE", dependencies: [MediaQuery])\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "EEE", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
- '├Text("F")\n'
+ '├Text("F", dependencies: [MediaQuery])\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "F", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
- '├Text("G")\n'
+ '├Text("G", dependencies: [MediaQuery])\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "G", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
- '├Text("H")\n'
+ '├Text("H", dependencies: [MediaQuery])\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "H", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
- '└Text("III")\n'
+ '└Text("III", dependencies: [MediaQuery])\n'
' └RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "III", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n',
),
);
diff --git a/packages/flutter_test/test/widget_tester_test.dart b/packages/flutter_test/test/widget_tester_test.dart
index a0b4f8a..713406e 100644
--- a/packages/flutter_test/test/widget_tester_test.dart
+++ b/packages/flutter_test/test/widget_tester_test.dart
@@ -99,7 +99,7 @@
final String? message = failure.message;
expect(message, contains('Expected: no matching nodes in the widget tree\n'));
- expect(message, contains('Actual: _TextFinder:<exactly one widget with text "foo": Text("foo", textDirection: ltr)>\n'));
+ expect(message, contains('Actual: _TextFinder:<exactly one widget with text "foo": Text("foo", textDirection: ltr, dependencies: [MediaQuery])>\n'));
expect(message, contains('Which: means one was found but none were expected\n'));
});
@@ -117,7 +117,7 @@
final String? message = failure.message;
expect(message, contains('Expected: no matching nodes in the widget tree\n'));
- expect(message, contains('Actual: _TextFinder:<exactly one widget with text "foo" (ignoring offstage widgets): Text("foo", textDirection: ltr)>\n'));
+ expect(message, contains('Actual: _TextFinder:<exactly one widget with text "foo" (ignoring offstage widgets): Text("foo", textDirection: ltr, dependencies: [MediaQuery])>\n'));
expect(message, contains('Which: means one was found but none were expected\n'));
});
});