mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
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>
This commit is contained in:
parent
3be330aaf9
commit
a45727d813
@ -1730,8 +1730,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
|
|||||||
child: title,
|
child: title,
|
||||||
);
|
);
|
||||||
|
|
||||||
final MediaQueryData? data = MediaQuery.maybeOf(context);
|
if (!widget.useInheritedMediaQuery || MediaQuery.maybeOf(context) == null) {
|
||||||
if (!widget.useInheritedMediaQuery || data == null) {
|
|
||||||
child = MediaQuery.fromWindow(
|
child = MediaQuery.fromWindow(
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
@ -138,8 +138,8 @@ enum _MediaQueryAspect {
|
|||||||
class MediaQueryData {
|
class MediaQueryData {
|
||||||
/// Creates data for a media query with explicit values.
|
/// Creates data for a media query with explicit values.
|
||||||
///
|
///
|
||||||
/// Consider using [MediaQueryData.fromWindow] to create data based on a
|
/// Consider using [MediaQueryData.fromView] to create data based on a
|
||||||
/// [dart:ui.PlatformDispatcher].
|
/// [dart:ui.FlutterView].
|
||||||
const MediaQueryData({
|
const MediaQueryData({
|
||||||
this.size = Size.zero,
|
this.size = Size.zero,
|
||||||
this.devicePixelRatio = 1.0,
|
this.devicePixelRatio = 1.0,
|
||||||
@ -167,24 +167,60 @@ class MediaQueryData {
|
|||||||
/// window's metrics change. For example, see
|
/// window's metrics change. For example, see
|
||||||
/// [WidgetsBindingObserver.didChangeMetrics] or
|
/// [WidgetsBindingObserver.didChangeMetrics] or
|
||||||
/// [dart:ui.PlatformDispatcher.onMetricsChanged].
|
/// [dart:ui.PlatformDispatcher.onMetricsChanged].
|
||||||
MediaQueryData.fromWindow(ui.FlutterView window)
|
factory MediaQueryData.fromWindow(ui.FlutterView window) => MediaQueryData.fromView(window);
|
||||||
: size = window.physicalSize / window.devicePixelRatio,
|
|
||||||
devicePixelRatio = window.devicePixelRatio,
|
/// Creates data for a [MediaQuery] based on the given `view`.
|
||||||
textScaleFactor = window.platformDispatcher.textScaleFactor,
|
///
|
||||||
platformBrightness = window.platformDispatcher.platformBrightness,
|
/// If provided, the `platformData` is used to fill in the platform-specific
|
||||||
padding = EdgeInsets.fromWindowPadding(window.padding, window.devicePixelRatio),
|
/// aspects of the newly created [MediaQueryData]. If `platformData` is null,
|
||||||
viewPadding = EdgeInsets.fromWindowPadding(window.viewPadding, window.devicePixelRatio),
|
/// the `view`'s [PlatformDispatcher] is consulted to construct the
|
||||||
viewInsets = EdgeInsets.fromWindowPadding(window.viewInsets, window.devicePixelRatio),
|
/// platform-specific data.
|
||||||
systemGestureInsets = EdgeInsets.fromWindowPadding(window.systemGestureInsets, window.devicePixelRatio),
|
///
|
||||||
accessibleNavigation = window.platformDispatcher.accessibilityFeatures.accessibleNavigation,
|
/// Data which is exposed directly on the [FlutterView] is considered
|
||||||
invertColors = window.platformDispatcher.accessibilityFeatures.invertColors,
|
/// view-specific. Data which is only exposed via the
|
||||||
disableAnimations = window.platformDispatcher.accessibilityFeatures.disableAnimations,
|
/// [FlutterView.platformDispatcher] property is considered platform-specific.
|
||||||
boldText = window.platformDispatcher.accessibilityFeatures.boldText,
|
///
|
||||||
highContrast = window.platformDispatcher.accessibilityFeatures.highContrast,
|
/// Callers of this method should ensure that they also register for
|
||||||
alwaysUse24HourFormat = window.platformDispatcher.alwaysUse24HourFormat,
|
/// notifications so that the [MediaQueryData] can be updated when any data
|
||||||
navigationMode = NavigationMode.traditional,
|
/// used to construct it changes. Notifications to consider are:
|
||||||
gestureSettings = DeviceGestureSettings.fromWindow(window),
|
///
|
||||||
displayFeatures = window.displayFeatures;
|
/// * [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).
|
/// The size of the media in logical pixels (e.g, the size of the screen).
|
||||||
///
|
///
|
||||||
@ -889,17 +925,43 @@ class MediaQuery extends InheritedModel<_MediaQueryAspect> {
|
|||||||
/// and its dependents are updated when `window` changes, instead of
|
/// and its dependents are updated when `window` changes, instead of
|
||||||
/// rebuilding the whole widget tree.
|
/// 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.
|
/// The [child] argument is required and must not be null.
|
||||||
static Widget fromWindow({
|
static Widget fromWindow({
|
||||||
Key? key,
|
Key? key,
|
||||||
required Widget child,
|
required Widget child,
|
||||||
}) {
|
}) {
|
||||||
return _MediaQueryFromWindow(
|
return _MediaQueryFromView(
|
||||||
key: key,
|
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,
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1399,94 +1461,102 @@ enum NavigationMode {
|
|||||||
directional,
|
directional,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides a [MediaQuery] which is built and updated using the latest
|
class _MediaQueryFromView extends StatefulWidget {
|
||||||
/// [WidgetsBinding.window] values.
|
const _MediaQueryFromView({
|
||||||
///
|
|
||||||
/// 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({
|
|
||||||
super.key,
|
super.key,
|
||||||
|
required this.view,
|
||||||
|
this.ignoreParentData = false,
|
||||||
required this.child,
|
required this.child,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// {@macro flutter.widgets.ProxyWidget.child}
|
final FlutterView view;
|
||||||
|
final bool ignoreParentData;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
@override
|
@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
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addObserver(this);
|
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
|
@override
|
||||||
void didChangeAccessibilityFeatures() {
|
void didChangeAccessibilityFeatures() {
|
||||||
setState(() {
|
// If we have a parent, it dictates our accessibility features. If we don't
|
||||||
// The properties of window have changed. We use them in our build
|
// have a parent, we get our accessibility features straight from the
|
||||||
// function, so we need setState(), but we don't cache anything locally.
|
// PlatformDispatcher and need to update our data in response to the
|
||||||
});
|
// PlatformDispatcher changing its accessibility features setting.
|
||||||
|
if (_parentData == null) {
|
||||||
|
_updateData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// METRICS
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeMetrics() {
|
void didChangeMetrics() {
|
||||||
setState(() {
|
_updateData();
|
||||||
// The properties of window have changed. We use them in our build
|
|
||||||
// function, so we need setState(), but we don't cache anything locally.
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeTextScaleFactor() {
|
void didChangeTextScaleFactor() {
|
||||||
setState(() {
|
// If we have a parent, it dictates our text scale factor. If we don't have
|
||||||
// The textScaleFactor property of window has changed. We reference
|
// a parent, we get our text scale factor from the PlatformDispatcher and
|
||||||
// window in our build function, so we need to call setState(), but
|
// need to update our data in response to the PlatformDispatcher changing
|
||||||
// we don't need to cache anything locally.
|
// its text scale factor setting.
|
||||||
});
|
if (_parentData == null) {
|
||||||
|
_updateData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RENDERING
|
|
||||||
@override
|
@override
|
||||||
void didChangePlatformBrightness() {
|
void didChangePlatformBrightness() {
|
||||||
setState(() {
|
// If we have a parent, it dictates our platform brightness. If we don't
|
||||||
// The platformBrightness property of window has changed. We reference
|
// have a parent, we get our platform brightness from the PlatformDispatcher
|
||||||
// window in our build function, so we need to call setState(), but
|
// and need to update our data in response to the PlatformDispatcher
|
||||||
// we don't need to cache anything locally.
|
// changing its platform brightness setting.
|
||||||
});
|
if (_parentData == null) {
|
||||||
}
|
_updateData();
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
|
|
||||||
if (!kReleaseMode) {
|
|
||||||
data = data.copyWith(platformBrightness: debugBrightnessOverride);
|
|
||||||
}
|
}
|
||||||
return MediaQuery(
|
|
||||||
data: data,
|
|
||||||
child: widget.child,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -1494,4 +1564,18 @@ class _MediaQueryFromWindowState extends State<_MediaQueryFromWindow> with Widge
|
|||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
super.dispose();
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,14 @@ import 'dart:ui' show FlutterView;
|
|||||||
|
|
||||||
import 'framework.dart';
|
import 'framework.dart';
|
||||||
import 'lookup_boundary.dart';
|
import 'lookup_boundary.dart';
|
||||||
|
import 'media_query.dart';
|
||||||
|
|
||||||
/// Injects a [FlutterView] into the tree and makes it available to descendants
|
/// Injects a [FlutterView] into the tree and makes it available to descendants
|
||||||
/// within the same [LookupBoundary] via [View.of] and [View.maybeOf].
|
/// 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
|
/// 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
|
/// extended to actually bootstrap the render tree that is going to be rendered
|
||||||
/// into the provided [view]. This will enable rendering content into multiple
|
/// into the provided [view]. This will enable rendering content into multiple
|
||||||
@ -20,15 +24,26 @@ import 'lookup_boundary.dart';
|
|||||||
/// [FlutterView] must never exist within the same widget tree at the same time.
|
/// [FlutterView] must never exist within the same widget tree at the same time.
|
||||||
/// Internally, this limitation is enforced by a [GlobalObjectKey] that derives
|
/// Internally, this limitation is enforced by a [GlobalObjectKey] that derives
|
||||||
/// its identity from the [view] provided to this widget.
|
/// 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.
|
/// 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.
|
/// The [FlutterView] to be injected into the tree.
|
||||||
final FlutterView view;
|
final FlutterView view;
|
||||||
|
|
||||||
|
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
@override
|
@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.
|
/// Returns the [FlutterView] that the provided `context` will render into.
|
||||||
///
|
///
|
||||||
@ -47,7 +62,7 @@ class View extends InheritedWidget {
|
|||||||
/// * [View.of], which throws instead of returning null if no [FlutterView]
|
/// * [View.of], which throws instead of returning null if no [FlutterView]
|
||||||
/// is found.
|
/// is found.
|
||||||
static FlutterView? maybeOf(BuildContext context) {
|
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.
|
/// Returns the [FlutterView] that the provided `context` will render into.
|
||||||
@ -70,7 +85,7 @@ class View extends InheritedWidget {
|
|||||||
final FlutterView? result = maybeOf(context);
|
final FlutterView? result = maybeOf(context);
|
||||||
assert(() {
|
assert(() {
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
final bool hiddenByBoundary = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<View>(context);
|
final bool hiddenByBoundary = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<_ViewScope>(context);
|
||||||
final List<DiagnosticsNode> information = <DiagnosticsNode>[
|
final List<DiagnosticsNode> information = <DiagnosticsNode>[
|
||||||
if (hiddenByBoundary) ...<DiagnosticsNode>[
|
if (hiddenByBoundary) ...<DiagnosticsNode>[
|
||||||
ErrorSummary('View.of() was called with a context that does not have access to a View widget.'),
|
ErrorSummary('View.of() was called with a context that does not have access to a View widget.'),
|
||||||
@ -92,3 +107,12 @@ class View extends InheritedWidget {
|
|||||||
return result!;
|
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;
|
||||||
|
}
|
||||||
|
@ -193,7 +193,7 @@ void main() {
|
|||||||
' Semantics\n'
|
' Semantics\n'
|
||||||
' Localizations\n'
|
' Localizations\n'
|
||||||
' MediaQuery\n'
|
' MediaQuery\n'
|
||||||
' _MediaQueryFromWindow\n'
|
' _MediaQueryFromView\n'
|
||||||
' Semantics\n'
|
' Semantics\n'
|
||||||
' _FocusInheritedScope\n'
|
' _FocusInheritedScope\n'
|
||||||
' Focus\n'
|
' Focus\n'
|
||||||
@ -235,6 +235,9 @@ void main() {
|
|||||||
' HeroControllerScope\n'
|
' HeroControllerScope\n'
|
||||||
' ScrollConfiguration\n'
|
' ScrollConfiguration\n'
|
||||||
' MaterialApp\n'
|
' MaterialApp\n'
|
||||||
|
' MediaQuery\n'
|
||||||
|
' _MediaQueryFromView\n'
|
||||||
|
' _ViewScope\n'
|
||||||
' View-[GlobalObjectKey TestWindow#00000]\n'
|
' View-[GlobalObjectKey TestWindow#00000]\n'
|
||||||
' [root]\n'
|
' [root]\n'
|
||||||
' Typically, the Scaffold widget is introduced by the MaterialApp\n'
|
' Typically, the Scaffold widget is introduced by the MaterialApp\n'
|
||||||
@ -251,18 +254,15 @@ void main() {
|
|||||||
);
|
);
|
||||||
await tester.pumpWidget(Directionality(
|
await tester.pumpWidget(Directionality(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
child: MediaQuery(
|
child: ScaffoldMessenger(
|
||||||
data: const MediaQueryData(),
|
key: scaffoldMessengerKey,
|
||||||
child: ScaffoldMessenger(
|
child: Builder(
|
||||||
key: scaffoldMessengerKey,
|
builder: (BuildContext context) {
|
||||||
child: Builder(
|
return Scaffold(
|
||||||
builder: (BuildContext context) {
|
key: scaffoldKey,
|
||||||
return Scaffold(
|
body: Container(),
|
||||||
key: scaffoldKey,
|
);
|
||||||
body: Container(),
|
},
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@ -278,12 +278,9 @@ void main() {
|
|||||||
// Pump widget to rebuild without ScaffoldMessenger
|
// Pump widget to rebuild without ScaffoldMessenger
|
||||||
await tester.pumpWidget(Directionality(
|
await tester.pumpWidget(Directionality(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
child: MediaQuery(
|
child: Scaffold(
|
||||||
data: const MediaQueryData(),
|
key: scaffoldKey,
|
||||||
child: Scaffold(
|
body: Container(),
|
||||||
key: scaffoldKey,
|
|
||||||
body: Container(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
// Tap SnackBarAction to dismiss.
|
// Tap SnackBarAction to dismiss.
|
||||||
@ -378,8 +375,10 @@ void main() {
|
|||||||
' ScrollNotificationObserver\n'
|
' ScrollNotificationObserver\n'
|
||||||
' _ScaffoldScope\n'
|
' _ScaffoldScope\n'
|
||||||
' Scaffold-[LabeledGlobalKey<ScaffoldState>#00000]\n'
|
' Scaffold-[LabeledGlobalKey<ScaffoldState>#00000]\n'
|
||||||
' MediaQuery\n'
|
|
||||||
' Directionality\n'
|
' Directionality\n'
|
||||||
|
' MediaQuery\n'
|
||||||
|
' _MediaQueryFromView\n'
|
||||||
|
' _ViewScope\n'
|
||||||
' View-[GlobalObjectKey TestWindow#00000]\n'
|
' View-[GlobalObjectKey TestWindow#00000]\n'
|
||||||
' [root]\n'
|
' [root]\n'
|
||||||
' Typically, the ScaffoldMessenger widget is introduced by the\n'
|
' Typically, the ScaffoldMessenger widget is introduced by the\n'
|
||||||
|
@ -136,12 +136,6 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await tester.pumpWidget(boilerplate(Scaffold(
|
|
||||||
appBar: AppBar(title: const Text('Title')),
|
|
||||||
body: Container(key: bodyKey),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
expect(tester.takeException(), isFlutterError);
|
|
||||||
|
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
@ -2391,24 +2385,21 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpWidget(Directionality(
|
await tester.pumpWidget(Directionality(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
child: MediaQuery(
|
child: Scaffold(
|
||||||
data: const MediaQueryData(),
|
body: Builder(
|
||||||
child: Scaffold(
|
builder: (BuildContext context) {
|
||||||
body: Builder(
|
return GestureDetector(
|
||||||
builder: (BuildContext context) {
|
key: tapTarget,
|
||||||
return GestureDetector(
|
onTap: () {
|
||||||
key: tapTarget,
|
ScaffoldMessenger.of(context);
|
||||||
onTap: () {
|
},
|
||||||
ScaffoldMessenger.of(context);
|
behavior: HitTestBehavior.opaque,
|
||||||
},
|
child: const SizedBox(
|
||||||
behavior: HitTestBehavior.opaque,
|
height: 100.0,
|
||||||
child: const SizedBox(
|
width: 100.0,
|
||||||
height: 100.0,
|
),
|
||||||
width: 100.0,
|
);
|
||||||
),
|
},
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@ -2459,8 +2450,10 @@ void main() {
|
|||||||
' ScrollNotificationObserver\n'
|
' ScrollNotificationObserver\n'
|
||||||
' _ScaffoldScope\n'
|
' _ScaffoldScope\n'
|
||||||
' Scaffold\n'
|
' Scaffold\n'
|
||||||
' MediaQuery\n'
|
|
||||||
' Directionality\n'
|
' Directionality\n'
|
||||||
|
' MediaQuery\n'
|
||||||
|
' _MediaQueryFromView\n'
|
||||||
|
' _ViewScope\n'
|
||||||
' View-[GlobalObjectKey TestWindow#e6136]\n'
|
' View-[GlobalObjectKey TestWindow#e6136]\n'
|
||||||
' [root]\n'
|
' [root]\n'
|
||||||
' Typically, the ScaffoldMessenger widget is introduced by the\n'
|
' Typically, the ScaffoldMessenger widget is introduced by the\n'
|
||||||
|
@ -77,7 +77,7 @@ void main() {
|
|||||||
' │ decoration: BoxDecoration:\n'
|
' │ decoration: BoxDecoration:\n'
|
||||||
' │ color: Color(0xff0000ff)\n'
|
' │ color: Color(0xff0000ff)\n'
|
||||||
' │ configuration: ImageConfiguration(bundle:\n'
|
' │ configuration: ImageConfiguration(bundle:\n'
|
||||||
' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' │ android)\n'
|
' │ android)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderLimitedBox#00000\n'
|
' └─child: RenderLimitedBox#00000\n'
|
||||||
|
@ -644,6 +644,32 @@ void main() {
|
|||||||
expect(MediaQuery.of(capturedContext), isNotNull);
|
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 {
|
testWidgets('WidgetsApp provides meta based shortcuts for iOS and macOS', (WidgetTester tester) async {
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
final SelectAllSpy selectAllSpy = SelectAllSpy();
|
final SelectAllSpy selectAllSpy = SelectAllSpy();
|
||||||
|
@ -78,7 +78,7 @@ void main() {
|
|||||||
' │ decoration: BoxDecoration:\n'
|
' │ decoration: BoxDecoration:\n'
|
||||||
' │ color: Color(0x7f0000ff)\n'
|
' │ color: Color(0x7f0000ff)\n'
|
||||||
' │ configuration: ImageConfiguration(bundle:\n'
|
' │ configuration: ImageConfiguration(bundle:\n'
|
||||||
' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' │ android)\n'
|
' │ android)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─child: _RenderColoredBox#00000\n'
|
' └─child: _RenderColoredBox#00000\n'
|
||||||
@ -114,7 +114,7 @@ void main() {
|
|||||||
' decoration: BoxDecoration:\n'
|
' decoration: BoxDecoration:\n'
|
||||||
' color: Color(0xffffff00)\n'
|
' color: Color(0xffffff00)\n'
|
||||||
' configuration: ImageConfiguration(bundle:\n'
|
' configuration: ImageConfiguration(bundle:\n'
|
||||||
' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' android)\n',
|
' android)\n',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -123,7 +123,8 @@ void main() {
|
|||||||
box.toStringDeep(),
|
box.toStringDeep(),
|
||||||
equalsIgnoringHashCodes(
|
equalsIgnoringHashCodes(
|
||||||
'RenderPadding#00000 relayoutBoundary=up1\n'
|
'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'
|
' │ TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
|
||||||
@ -132,6 +133,7 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
||||||
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
|
||||||
|
' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: offset=Offset(5.0, 5.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
|
||||||
@ -140,20 +142,21 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderDecoratedBox#00000\n'
|
' └─child: RenderDecoratedBox#00000\n'
|
||||||
' │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\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'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ size: Size(53.0, 78.0)\n'
|
' │ size: Size(53.0, 78.0)\n'
|
||||||
' │ decoration: BoxDecoration:\n'
|
' │ decoration: BoxDecoration:\n'
|
||||||
' │ color: Color(0x7f0000ff)\n'
|
' │ color: Color(0x7f0000ff)\n'
|
||||||
' │ configuration: ImageConfiguration(bundle:\n'
|
' │ configuration: ImageConfiguration(bundle:\n'
|
||||||
' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' │ android)\n'
|
' │ android)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─child: _RenderColoredBox#00000\n'
|
' └─child: _RenderColoredBox#00000\n'
|
||||||
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
|
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
|
||||||
' │ Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
|
' │ Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
|
||||||
' │ [root]\n'
|
' │ _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ size: Size(53.0, 78.0)\n'
|
' │ size: Size(53.0, 78.0)\n'
|
||||||
@ -161,8 +164,8 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderPadding#00000\n'
|
' └─child: RenderPadding#00000\n'
|
||||||
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
|
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
|
||||||
' │ Padding ← Container ← Align ← View-[GlobalObjectKey\n'
|
' │ Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
|
||||||
' │ TestWindow#00000] ← [root]\n'
|
' │ ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ size: Size(53.0, 78.0)\n'
|
' │ size: Size(53.0, 78.0)\n'
|
||||||
@ -170,8 +173,9 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderPositionedBox#00000\n'
|
' └─child: RenderPositionedBox#00000\n'
|
||||||
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
||||||
' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
|
||||||
|
' │ TestWindow#00000] ← ⋯\n'
|
||||||
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
|
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
|
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
|
||||||
' │ size: Size(39.0, 64.0)\n'
|
' │ size: Size(39.0, 64.0)\n'
|
||||||
@ -181,8 +185,8 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
|
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
|
||||||
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
||||||
' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ _MediaQueryFromView ← _ViewScope ← ⋯\n'
|
||||||
' │ parentData: offset=Offset(14.0, 31.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
|
||||||
' │ size: Size(25.0, 33.0)\n'
|
' │ size: Size(25.0, 33.0)\n'
|
||||||
@ -191,15 +195,15 @@ void main() {
|
|||||||
' └─child: RenderDecoratedBox#00000\n'
|
' └─child: RenderDecoratedBox#00000\n'
|
||||||
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
|
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
|
||||||
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
|
||||||
' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' MediaQuery ← _MediaQueryFromView ← ⋯\n'
|
||||||
' parentData: <none> (can use size)\n'
|
' parentData: <none> (can use size)\n'
|
||||||
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
|
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
|
||||||
' size: Size(25.0, 33.0)\n'
|
' size: Size(25.0, 33.0)\n'
|
||||||
' decoration: BoxDecoration:\n'
|
' decoration: BoxDecoration:\n'
|
||||||
' color: Color(0xffffff00)\n'
|
' color: Color(0xffffff00)\n'
|
||||||
' configuration: ImageConfiguration(bundle:\n'
|
' configuration: ImageConfiguration(bundle:\n'
|
||||||
' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' android)\n'
|
' android)\n',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -207,7 +211,8 @@ void main() {
|
|||||||
box.toStringDeep(minLevel: DiagnosticLevel.fine),
|
box.toStringDeep(minLevel: DiagnosticLevel.fine),
|
||||||
equalsIgnoringHashCodes(
|
equalsIgnoringHashCodes(
|
||||||
'RenderPadding#00000 relayoutBoundary=up1\n'
|
'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'
|
' │ TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
|
||||||
@ -219,6 +224,7 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
||||||
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
|
||||||
|
' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: offset=Offset(5.0, 5.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
|
||||||
@ -229,7 +235,8 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderDecoratedBox#00000\n'
|
' └─child: RenderDecoratedBox#00000\n'
|
||||||
' │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\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'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -244,13 +251,13 @@ void main() {
|
|||||||
' │ gradient: null\n'
|
' │ gradient: null\n'
|
||||||
' │ shape: rectangle\n'
|
' │ shape: rectangle\n'
|
||||||
' │ configuration: ImageConfiguration(bundle:\n'
|
' │ configuration: ImageConfiguration(bundle:\n'
|
||||||
' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' │ android)\n'
|
' │ android)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─child: _RenderColoredBox#00000\n'
|
' └─child: _RenderColoredBox#00000\n'
|
||||||
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
|
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
|
||||||
' │ Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
|
' │ Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
|
||||||
' │ [root]\n'
|
' │ _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -260,8 +267,8 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderPadding#00000\n'
|
' └─child: RenderPadding#00000\n'
|
||||||
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
|
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
|
||||||
' │ Padding ← Container ← Align ← View-[GlobalObjectKey\n'
|
' │ Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
|
||||||
' │ TestWindow#00000] ← [root]\n'
|
' │ ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -272,8 +279,9 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderPositionedBox#00000\n'
|
' └─child: RenderPositionedBox#00000\n'
|
||||||
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
||||||
' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
|
||||||
|
' │ TestWindow#00000] ← ⋯\n'
|
||||||
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
|
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
|
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -286,8 +294,8 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
|
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
|
||||||
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
||||||
' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ _MediaQueryFromView ← _ViewScope ← ⋯\n'
|
||||||
' │ parentData: offset=Offset(14.0, 31.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -298,7 +306,7 @@ void main() {
|
|||||||
' └─child: RenderDecoratedBox#00000\n'
|
' └─child: RenderDecoratedBox#00000\n'
|
||||||
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
|
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
|
||||||
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
|
||||||
' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' MediaQuery ← _MediaQueryFromView ← ⋯\n'
|
||||||
' parentData: <none> (can use size)\n'
|
' parentData: <none> (can use size)\n'
|
||||||
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
|
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
|
||||||
' layer: null\n'
|
' layer: null\n'
|
||||||
@ -313,8 +321,8 @@ void main() {
|
|||||||
' gradient: null\n'
|
' gradient: null\n'
|
||||||
' shape: rectangle\n'
|
' shape: rectangle\n'
|
||||||
' configuration: ImageConfiguration(bundle:\n'
|
' configuration: ImageConfiguration(bundle:\n'
|
||||||
' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' android)\n'
|
' android)\n',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -323,7 +331,8 @@ void main() {
|
|||||||
equalsIgnoringHashCodes(
|
equalsIgnoringHashCodes(
|
||||||
'RenderPadding#00000 relayoutBoundary=up1\n'
|
'RenderPadding#00000 relayoutBoundary=up1\n'
|
||||||
' │ needsCompositing: false\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'
|
' │ TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
|
||||||
@ -338,6 +347,7 @@ void main() {
|
|||||||
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
||||||
' │ needsCompositing: false\n'
|
' │ needsCompositing: false\n'
|
||||||
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ creator: ConstrainedBox ← Padding ← Container ← Align ←\n'
|
||||||
|
' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: offset=Offset(5.0, 5.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
|
||||||
@ -351,7 +361,8 @@ void main() {
|
|||||||
' └─child: RenderDecoratedBox#00000\n'
|
' └─child: RenderDecoratedBox#00000\n'
|
||||||
' │ needsCompositing: false\n'
|
' │ needsCompositing: false\n'
|
||||||
' │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\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'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -368,14 +379,14 @@ void main() {
|
|||||||
' │ gradient: null\n'
|
' │ gradient: null\n'
|
||||||
' │ shape: rectangle\n'
|
' │ shape: rectangle\n'
|
||||||
' │ configuration: ImageConfiguration(bundle:\n'
|
' │ configuration: ImageConfiguration(bundle:\n'
|
||||||
' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' │ PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' │ android)\n'
|
' │ android)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─child: _RenderColoredBox#00000\n'
|
' └─child: _RenderColoredBox#00000\n'
|
||||||
' │ needsCompositing: false\n'
|
' │ needsCompositing: false\n'
|
||||||
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
|
' │ creator: ColoredBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
|
||||||
' │ Container ← Align ← View-[GlobalObjectKey TestWindow#00000] ←\n'
|
' │ Container ← Align ← MediaQuery ← _MediaQueryFromView ←\n'
|
||||||
' │ [root]\n'
|
' │ _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -388,8 +399,8 @@ void main() {
|
|||||||
' └─child: RenderPadding#00000\n'
|
' └─child: RenderPadding#00000\n'
|
||||||
' │ needsCompositing: false\n'
|
' │ needsCompositing: false\n'
|
||||||
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
|
' │ creator: Padding ← ColoredBox ← DecoratedBox ← ConstrainedBox ←\n'
|
||||||
' │ Padding ← Container ← Align ← View-[GlobalObjectKey\n'
|
' │ Padding ← Container ← Align ← MediaQuery ← _MediaQueryFromView\n'
|
||||||
' │ TestWindow#00000] ← [root]\n'
|
' │ ← _ViewScope ← View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -403,8 +414,9 @@ void main() {
|
|||||||
' └─child: RenderPositionedBox#00000\n'
|
' └─child: RenderPositionedBox#00000\n'
|
||||||
' │ needsCompositing: false\n'
|
' │ needsCompositing: false\n'
|
||||||
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
' │ creator: Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
||||||
' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
|
||||||
|
' │ TestWindow#00000] ← ⋯\n'
|
||||||
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
|
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
|
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -420,8 +432,8 @@ void main() {
|
|||||||
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
|
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
|
||||||
' │ needsCompositing: false\n'
|
' │ needsCompositing: false\n'
|
||||||
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
' │ creator: SizedBox ← Align ← Padding ← ColoredBox ← DecoratedBox ←\n'
|
||||||
' │ ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' │ ConstrainedBox ← Padding ← Container ← Align ← MediaQuery ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ _MediaQueryFromView ← _ViewScope ← ⋯\n'
|
||||||
' │ parentData: offset=Offset(14.0, 31.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
|
||||||
' │ layer: null\n'
|
' │ layer: null\n'
|
||||||
@ -435,7 +447,7 @@ void main() {
|
|||||||
' needsCompositing: false\n'
|
' needsCompositing: false\n'
|
||||||
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
|
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← ColoredBox ←\n'
|
||||||
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
|
' DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
|
||||||
' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' MediaQuery ← _MediaQueryFromView ← ⋯\n'
|
||||||
' parentData: <none> (can use size)\n'
|
' parentData: <none> (can use size)\n'
|
||||||
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
|
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
|
||||||
' layer: null\n'
|
' layer: null\n'
|
||||||
@ -452,8 +464,8 @@ void main() {
|
|||||||
' gradient: null\n'
|
' gradient: null\n'
|
||||||
' shape: rectangle\n'
|
' shape: rectangle\n'
|
||||||
' configuration: ImageConfiguration(bundle:\n'
|
' configuration: ImageConfiguration(bundle:\n'
|
||||||
' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
|
' PlatformAssetBundle#00000(), devicePixelRatio: 3.0, platform:\n'
|
||||||
' android)\n'
|
' android)\n',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -372,7 +372,8 @@ void main() {
|
|||||||
' in its parent data.\n'
|
' in its parent data.\n'
|
||||||
' The following child has no ID: RenderConstrainedBox#00000 NEEDS-LAYOUT NEEDS-PAINT:\n'
|
' The following child has no ID: RenderConstrainedBox#00000 NEEDS-LAYOUT NEEDS-PAINT:\n'
|
||||||
' creator: ConstrainedBox ← Container ← LayoutWithMissingId ←\n'
|
' creator: ConstrainedBox ← Container ← LayoutWithMissingId ←\n'
|
||||||
' CustomMultiChildLayout ← Center ← View-[GlobalObjectKey\n'
|
' CustomMultiChildLayout ← Center ← MediaQuery ←\n'
|
||||||
|
' _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
|
||||||
' TestWindow#00000] ← [root]\n'
|
' TestWindow#00000] ← [root]\n'
|
||||||
' parentData: offset=Offset(0.0, 0.0); id=null\n'
|
' parentData: offset=Offset(0.0, 0.0); id=null\n'
|
||||||
' constraints: MISSING\n'
|
' constraints: MISSING\n'
|
||||||
|
@ -96,8 +96,11 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('debugCheckHasMediaQuery control test', (WidgetTester tester) async {
|
testWidgets('debugCheckHasMediaQuery control test', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
// Cannot use tester.pumpWidget here because it wraps the widget in a View,
|
||||||
Builder(
|
// which introduces a MediaQuery ancestor.
|
||||||
|
await pumpWidgetWithoutViewWrapper(
|
||||||
|
tester: tester,
|
||||||
|
widget: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
late FlutterError error;
|
late FlutterError error;
|
||||||
try {
|
try {
|
||||||
@ -339,3 +342,9 @@ void main() {
|
|||||||
expect(renderObject.debugLayer?.debugCreator, isNotNull);
|
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();
|
||||||
|
}
|
||||||
|
@ -1228,8 +1228,9 @@ void main() {
|
|||||||
equalsIgnoringHashCodes(
|
equalsIgnoringHashCodes(
|
||||||
'FocusManager#00000\n'
|
'FocusManager#00000\n'
|
||||||
' │ primaryFocus: FocusNode#00000(Child 4 [PRIMARY FOCUS])\n'
|
' │ primaryFocus: FocusNode#00000(Child 4 [PRIMARY FOCUS])\n'
|
||||||
' │ primaryFocusCreator: Container-[GlobalKey#00000] ←\n'
|
' │ primaryFocusCreator: Container-[GlobalKey#00000] ← MediaQuery ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
|
||||||
|
' │ TestWindow#00000] ← [root]\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─rootScope: FocusScopeNode#00000(Root Focus Scope [IN FOCUS PATH])\n'
|
' └─rootScope: FocusScopeNode#00000(Root Focus Scope [IN FOCUS PATH])\n'
|
||||||
' │ IN FOCUS PATH\n'
|
' │ IN FOCUS PATH\n'
|
||||||
|
@ -30,7 +30,7 @@ class TestWidgetState extends State<TestWidget> {
|
|||||||
void main() {
|
void main() {
|
||||||
testWidgets('initState() is called when we are in the tree', (WidgetTester tester) async {
|
testWidgets('initState() is called when we are in the tree', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(const Parent(child: TestWidget()));
|
await tester.pumpWidget(const Parent(child: TestWidget()));
|
||||||
expect(ancestors, equals(<String>['Parent', 'View', 'RenderObjectToWidgetAdapter<RenderBox>']));
|
expect(ancestors, containsAllInOrder(<String>['Parent', 'View', 'RenderObjectToWidgetAdapter<RenderBox>']));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ void main() {
|
|||||||
' │ ScrollDirection.idle)\n'
|
' │ ScrollDirection.idle)\n'
|
||||||
' │ anchor: 0.0\n'
|
' │ anchor: 0.0\n'
|
||||||
' │\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'
|
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
|
||||||
' │ constraints: SliverConstraints(AxisDirection.down,\n'
|
' │ constraints: SliverConstraints(AxisDirection.down,\n'
|
||||||
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
|
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
|
||||||
@ -314,49 +314,63 @@ void main() {
|
|||||||
' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
|
' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
|
||||||
' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
|
' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
|
||||||
' │ cacheExtent: 850.0)\n'
|
' │ cacheExtent: 850.0)\n'
|
||||||
' │ currently live children: 0 to 2\n'
|
' │ padding: EdgeInsets.zero\n'
|
||||||
|
' │ textDirection: ltr\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' ├─child with index 0: RenderLimitedBox#00000\n'
|
' └─child: RenderSliverFixedExtentList#00000 relayoutBoundary=up2\n'
|
||||||
' │ │ parentData: index=0; layoutOffset=0.0\n'
|
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
|
||||||
' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
|
' │ constraints: SliverConstraints(AxisDirection.down,\n'
|
||||||
' │ │ size: Size(800.0, 400.0)\n'
|
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
|
||||||
' │ │ maxWidth: 400.0\n'
|
' │ 0.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n'
|
||||||
' │ │ maxHeight: 400.0\n'
|
' │ crossAxisDirection: AxisDirection.right,\n'
|
||||||
' │ │\n'
|
' │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 850.0,\n'
|
||||||
' │ └─child: RenderCustomPaint#00000\n'
|
' │ cacheOrigin: 0.0)\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
|
||||||
' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
|
' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
|
||||||
' │ size: Size(800.0, 400.0)\n'
|
' │ cacheExtent: 850.0)\n'
|
||||||
' │ painter: _PlaceholderPainter#00000()\n'
|
' │ currently live children: 0 to 2\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'
|
' │\n'
|
||||||
' └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
|
' ├─child with index 0: RenderLimitedBox#00000\n'
|
||||||
' parentData: <none> (can use size)\n'
|
' │ │ parentData: index=0; layoutOffset=0.0\n'
|
||||||
' constraints: BoxConstraints(w=800.0, h=400.0)\n'
|
' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
|
||||||
' size: Size(800.0, 400.0)\n'
|
' │ │ size: Size(800.0, 400.0)\n'
|
||||||
' painter: _PlaceholderPainter#00000()\n'
|
' │ │ maxWidth: 400.0\n'
|
||||||
' preferredSize: Size(Infinity, Infinity)\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);
|
const GlobalObjectKey<_LeafState>(0).currentState!.setKeepAlive(true);
|
||||||
await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0));
|
await tester.drag(find.byType(ListView), const Offset(0.0, -1000.0));
|
||||||
@ -463,7 +477,7 @@ void main() {
|
|||||||
' │ ScrollDirection.idle)\n'
|
' │ ScrollDirection.idle)\n'
|
||||||
' │ anchor: 0.0\n'
|
' │ anchor: 0.0\n'
|
||||||
' │\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'
|
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
|
||||||
' │ constraints: SliverConstraints(AxisDirection.down,\n'
|
' │ constraints: SliverConstraints(AxisDirection.down,\n'
|
||||||
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
|
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
|
||||||
@ -474,92 +488,105 @@ void main() {
|
|||||||
' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
|
' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
|
||||||
' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
|
' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
|
||||||
' │ cacheExtent: 1100.0)\n'
|
' │ cacheExtent: 1100.0)\n'
|
||||||
' │ currently live children: 4 to 7\n'
|
' │ padding: EdgeInsets.zero\n'
|
||||||
|
' │ textDirection: ltr\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' ├─child with index 4: RenderLimitedBox#00000 NEEDS-PAINT\n'
|
' └─child: RenderSliverFixedExtentList#00000 relayoutBoundary=up2\n'
|
||||||
' │ │ parentData: index=4; layoutOffset=1600.0\n'
|
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
|
||||||
' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
|
' │ constraints: SliverConstraints(AxisDirection.down,\n'
|
||||||
' │ │ size: Size(800.0, 400.0)\n'
|
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
|
||||||
' │ │ maxWidth: 400.0\n'
|
' │ 2000.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n'
|
||||||
' │ │ maxHeight: 400.0\n'
|
' │ crossAxisDirection: AxisDirection.right,\n'
|
||||||
' │ │\n'
|
' │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 1100.0,\n'
|
||||||
' │ └─child: RenderCustomPaint#00000 NEEDS-PAINT\n'
|
' │ cacheOrigin: -250.0)\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ geometry: SliverGeometry(scrollExtent: 40000.0, paintExtent:\n'
|
||||||
' │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
|
' │ 600.0, maxPaintExtent: 40000.0, hasVisualOverflow: true,\n'
|
||||||
' │ size: Size(800.0, 400.0)\n'
|
' │ cacheExtent: 1100.0)\n'
|
||||||
' │ painter: _PlaceholderPainter#00000()\n'
|
' │ currently live children: 4 to 7\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'
|
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderCustomPaint#00000\n'
|
' ├─child with index 4: RenderLimitedBox#00000 NEEDS-PAINT\n'
|
||||||
' parentData: <none> (can use size)\n'
|
' │ │ parentData: index=4; layoutOffset=1600.0\n'
|
||||||
' constraints: BoxConstraints(w=800.0, h=400.0)\n'
|
' │ │ constraints: BoxConstraints(w=800.0, h=400.0)\n'
|
||||||
' size: Size(800.0, 400.0)\n'
|
' │ │ size: Size(800.0, 400.0)\n'
|
||||||
' painter: _PlaceholderPainter#00000()\n'
|
' │ │ maxWidth: 400.0\n'
|
||||||
' preferredSize: Size(Infinity, Infinity)\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
|
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87876
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -326,7 +326,7 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
list.toStringDeep(minLevel: DiagnosticLevel.info),
|
list.toStringDeep(minLevel: DiagnosticLevel.info),
|
||||||
equalsIgnoringHashCodes(
|
equalsIgnoringHashCodes(
|
||||||
'RenderSliverList#00000 relayoutBoundary=up1\n'
|
'RenderSliverList#00000 relayoutBoundary=up2\n'
|
||||||
' │ needs compositing\n'
|
' │ needs compositing\n'
|
||||||
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
|
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
|
||||||
' │ constraints: SliverConstraints(AxisDirection.down,\n'
|
' │ constraints: SliverConstraints(AxisDirection.down,\n'
|
||||||
@ -339,7 +339,7 @@ void main() {
|
|||||||
' │ maxPaintExtent: 300.0, cacheExtent: 300.0)\n'
|
' │ maxPaintExtent: 300.0, cacheExtent: 300.0)\n'
|
||||||
' │ currently live children: 0 to 2\n'
|
' │ currently live children: 0 to 2\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' ├─child with index 0: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
|
' ├─child with index 0: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
|
||||||
' │ │ needs compositing\n'
|
' │ │ needs compositing\n'
|
||||||
' │ │ parentData: index=0; layoutOffset=0.0 (can use size)\n'
|
' │ │ parentData: index=0; layoutOffset=0.0 (can use size)\n'
|
||||||
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
||||||
@ -349,7 +349,7 @@ void main() {
|
|||||||
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
|
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
|
||||||
' │ │ repaints)\n'
|
' │ │ repaints)\n'
|
||||||
' │ │\n'
|
' │ │\n'
|
||||||
' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
|
' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
|
||||||
' │ │ parentData: <none> (can use size)\n'
|
' │ │ parentData: <none> (can use size)\n'
|
||||||
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
||||||
' │ │ size: Size(800.0, 100.0)\n'
|
' │ │ size: Size(800.0, 100.0)\n'
|
||||||
@ -368,7 +368,7 @@ void main() {
|
|||||||
' │ size: Size(800.0, 100.0)\n'
|
' │ size: Size(800.0, 100.0)\n'
|
||||||
' │ additionalConstraints: BoxConstraints(biggest)\n'
|
' │ additionalConstraints: BoxConstraints(biggest)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' ├─child with index 1: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
|
' ├─child with index 1: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
|
||||||
' │ │ needs compositing\n'
|
' │ │ needs compositing\n'
|
||||||
' │ │ parentData: index=1; layoutOffset=100.0 (can use size)\n'
|
' │ │ parentData: index=1; layoutOffset=100.0 (can use size)\n'
|
||||||
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
||||||
@ -378,7 +378,7 @@ void main() {
|
|||||||
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
|
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
|
||||||
' │ │ repaints)\n'
|
' │ │ repaints)\n'
|
||||||
' │ │\n'
|
' │ │\n'
|
||||||
' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
|
' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
|
||||||
' │ │ parentData: <none> (can use size)\n'
|
' │ │ parentData: <none> (can use size)\n'
|
||||||
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
||||||
' │ │ size: Size(800.0, 100.0)\n'
|
' │ │ size: Size(800.0, 100.0)\n'
|
||||||
@ -397,7 +397,7 @@ void main() {
|
|||||||
' │ size: Size(800.0, 100.0)\n'
|
' │ size: Size(800.0, 100.0)\n'
|
||||||
' │ additionalConstraints: BoxConstraints(biggest)\n'
|
' │ additionalConstraints: BoxConstraints(biggest)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─child with index 2: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
|
' └─child with index 2: RenderRepaintBoundary#00000 relayoutBoundary=up3\n'
|
||||||
' │ needs compositing\n'
|
' │ needs compositing\n'
|
||||||
' │ parentData: index=2; layoutOffset=200.0 (can use size)\n'
|
' │ parentData: index=2; layoutOffset=200.0 (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
||||||
@ -407,7 +407,7 @@ void main() {
|
|||||||
' │ diagnosis: insufficient data to draw conclusion (less than five\n'
|
' │ diagnosis: insufficient data to draw conclusion (less than five\n'
|
||||||
' │ repaints)\n'
|
' │ repaints)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
|
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
|
||||||
' │ parentData: <none> (can use size)\n'
|
' │ parentData: <none> (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
|
||||||
' │ size: Size(800.0, 100.0)\n'
|
' │ size: Size(800.0, 100.0)\n'
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// 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/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -45,8 +45,11 @@ class _MediaQueryAspectVariant extends TestVariant<_MediaQueryAspectCase> {
|
|||||||
void main() {
|
void main() {
|
||||||
testWidgets('MediaQuery does not have a default', (WidgetTester tester) async {
|
testWidgets('MediaQuery does not have a default', (WidgetTester tester) async {
|
||||||
bool tested = false;
|
bool tested = false;
|
||||||
await tester.pumpWidget(
|
// Cannot use tester.pumpWidget here because it wraps the widget in a View,
|
||||||
Builder(
|
// which introduces a MediaQuery ancestor.
|
||||||
|
await pumpWidgetWithoutViewWrapper(
|
||||||
|
tester: tester,
|
||||||
|
widget: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
tested = true;
|
tested = true;
|
||||||
MediaQuery.of(context); // should throw
|
MediaQuery.of(context); // should throw
|
||||||
@ -108,8 +111,11 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('MediaQuery.maybeOf defaults to null', (WidgetTester tester) async {
|
testWidgets('MediaQuery.maybeOf defaults to null', (WidgetTester tester) async {
|
||||||
bool tested = false;
|
bool tested = false;
|
||||||
await tester.pumpWidget(
|
// Cannot use tester.pumpWidget here because it wraps the widget in a View,
|
||||||
Builder(
|
// which introduces a MediaQuery ancestor.
|
||||||
|
await pumpWidgetWithoutViewWrapper(
|
||||||
|
tester: tester,
|
||||||
|
widget: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final MediaQueryData? data = MediaQuery.maybeOf(context);
|
final MediaQueryData? data = MediaQuery.maybeOf(context);
|
||||||
expect(data, isNull);
|
expect(data, isNull);
|
||||||
@ -154,6 +160,358 @@ void main() {
|
|||||||
expect(data.displayFeatures, isEmpty);
|
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 {
|
testWidgets('MediaQueryData.copyWith defaults to source', (WidgetTester tester) async {
|
||||||
final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
|
final MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance.window);
|
||||||
final MediaQueryData copied = data.copyWith();
|
final MediaQueryData copied = data.copyWith();
|
||||||
@ -753,19 +1111,17 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('MediaQuery.fromWindow creates a MediaQuery', (WidgetTester tester) async {
|
testWidgets('MediaQuery.fromWindow creates a MediaQuery', (WidgetTester tester) async {
|
||||||
bool hasMediaQueryAsParentOutside = false;
|
MediaQuery? mediaQueryOutside;
|
||||||
bool hasMediaQueryAsParentInside = false;
|
MediaQuery? mediaQueryInside;
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Builder(
|
Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
hasMediaQueryAsParentOutside =
|
mediaQueryOutside = context.findAncestorWidgetOfExactType<MediaQuery>();
|
||||||
context.findAncestorWidgetOfExactType<MediaQuery>() != null;
|
|
||||||
return MediaQuery.fromWindow(
|
return MediaQuery.fromWindow(
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
hasMediaQueryAsParentInside =
|
mediaQueryInside = context.findAncestorWidgetOfExactType<MediaQuery>();
|
||||||
context.findAncestorWidgetOfExactType<MediaQuery>() != null;
|
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -774,8 +1130,8 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(hasMediaQueryAsParentOutside, false);
|
expect(mediaQueryInside, isNotNull);
|
||||||
expect(hasMediaQueryAsParentInside, true);
|
expect(mediaQueryOutside, isNot(mediaQueryInside));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('MediaQueryData.fromWindow is created using window values', (WidgetTester tester) async {
|
testWidgets('MediaQueryData.fromWindow is created using window values', (WidgetTester tester) async {
|
||||||
@ -1150,3 +1506,58 @@ void main() {
|
|||||||
]
|
]
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -2707,14 +2707,6 @@ void main() {
|
|||||||
semantics.dispose();
|
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 {
|
testWidgets('onTap is called upon tap', (WidgetTester tester) async {
|
||||||
int tapCount = 0;
|
int tapCount = 0;
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
|
@ -221,14 +221,16 @@ void main() {
|
|||||||
tester.renderObject(find.byType(_Diagonal)).toStringDeep(),
|
tester.renderObject(find.byType(_Diagonal)).toStringDeep(),
|
||||||
equalsIgnoringHashCodes(
|
equalsIgnoringHashCodes(
|
||||||
'_RenderDiagonal#00000 relayoutBoundary=up1\n'
|
'_RenderDiagonal#00000 relayoutBoundary=up1\n'
|
||||||
' │ creator: _Diagonal ← Align ← Directionality ←\n'
|
' │ creator: _Diagonal ← Align ← Directionality ← MediaQuery ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ _MediaQueryFromView ← _ViewScope ← View-[GlobalObjectKey\n'
|
||||||
|
' │ TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\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'
|
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
|
||||||
' │ size: Size(190.0, 220.0)\n'
|
' │ size: Size(190.0, 220.0)\n'
|
||||||
' │\n'
|
' │\n'
|
||||||
' ├─topLeft: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
' ├─topLeft: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
||||||
' │ creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
|
' │ creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
|
||||||
|
' │ MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
|
||||||
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' │ View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
|
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
|
||||||
' │ constraints: BoxConstraints(unconstrained)\n'
|
' │ constraints: BoxConstraints(unconstrained)\n'
|
||||||
@ -237,6 +239,7 @@ void main() {
|
|||||||
' │\n'
|
' │\n'
|
||||||
' └─bottomRight: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
' └─bottomRight: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
|
||||||
' creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
|
' creator: SizedBox ← _Diagonal ← Align ← Directionality ←\n'
|
||||||
|
' MediaQuery ← _MediaQueryFromView ← _ViewScope ←\n'
|
||||||
' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
' View-[GlobalObjectKey TestWindow#00000] ← [root]\n'
|
||||||
' parentData: offset=Offset(80.0, 100.0) (can use size)\n'
|
' parentData: offset=Offset(80.0, 100.0) (can use size)\n'
|
||||||
' constraints: BoxConstraints(unconstrained)\n'
|
' constraints: BoxConstraints(unconstrained)\n'
|
||||||
|
@ -879,24 +879,24 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
element.toStringDeep(minLevel: DiagnosticLevel.info),
|
element.toStringDeep(minLevel: DiagnosticLevel.info),
|
||||||
equalsIgnoringHashCodes(
|
equalsIgnoringHashCodes(
|
||||||
'Table-[GlobalKey#00000](dependencies: [Directionality], renderObject: RenderTable#00000)\n'
|
'Table-[GlobalKey#00000](dependencies: [Directionality, MediaQuery], renderObject: RenderTable#00000)\n'
|
||||||
'├Text("A")\n'
|
'├Text("A", dependencies: [MediaQuery])\n'
|
||||||
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "A", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\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'
|
'│└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'
|
'│└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'
|
'│└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'
|
'│└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'
|
'│└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'
|
'│└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'
|
'│└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',
|
' └RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "III", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -99,7 +99,7 @@ void main() {
|
|||||||
final String? message = failure.message;
|
final String? message = failure.message;
|
||||||
|
|
||||||
expect(message, contains('Expected: no matching nodes in the widget tree\n'));
|
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'));
|
expect(message, contains('Which: means one was found but none were expected\n'));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ void main() {
|
|||||||
final String? message = failure.message;
|
final String? message = failure.message;
|
||||||
|
|
||||||
expect(message, contains('Expected: no matching nodes in the widget tree\n'));
|
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'));
|
expect(message, contains('Which: means one was found but none were expected\n'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user