parent
f8d2615d49
commit
ea1182effd
@ -170,6 +170,7 @@ class CupertinoApp extends StatefulWidget {
|
|||||||
this.actions,
|
this.actions,
|
||||||
this.restorationScopeId,
|
this.restorationScopeId,
|
||||||
this.scrollBehavior,
|
this.scrollBehavior,
|
||||||
|
this.useInheritedMediaQuery = false,
|
||||||
}) : assert(routes != null),
|
}) : assert(routes != null),
|
||||||
assert(navigatorObservers != null),
|
assert(navigatorObservers != null),
|
||||||
assert(title != null),
|
assert(title != null),
|
||||||
@ -210,6 +211,7 @@ class CupertinoApp extends StatefulWidget {
|
|||||||
this.actions,
|
this.actions,
|
||||||
this.restorationScopeId,
|
this.restorationScopeId,
|
||||||
this.scrollBehavior,
|
this.scrollBehavior,
|
||||||
|
this.useInheritedMediaQuery = false,
|
||||||
}) : assert(title != null),
|
}) : assert(title != null),
|
||||||
assert(showPerformanceOverlay != null),
|
assert(showPerformanceOverlay != null),
|
||||||
assert(checkerboardRasterCacheImages != null),
|
assert(checkerboardRasterCacheImages != null),
|
||||||
@ -407,6 +409,9 @@ class CupertinoApp extends StatefulWidget {
|
|||||||
/// in a subtree.
|
/// in a subtree.
|
||||||
final ScrollBehavior? scrollBehavior;
|
final ScrollBehavior? scrollBehavior;
|
||||||
|
|
||||||
|
/// {@macro flutter.widgets.widgetsApp.useInheritedMediaQuery}
|
||||||
|
final bool useInheritedMediaQuery;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CupertinoApp> createState() => _CupertinoAppState();
|
State<CupertinoApp> createState() => _CupertinoAppState();
|
||||||
|
|
||||||
@ -530,6 +535,7 @@ class _CupertinoAppState extends State<CupertinoApp> {
|
|||||||
shortcuts: widget.shortcuts,
|
shortcuts: widget.shortcuts,
|
||||||
actions: widget.actions,
|
actions: widget.actions,
|
||||||
restorationScopeId: widget.restorationScopeId,
|
restorationScopeId: widget.restorationScopeId,
|
||||||
|
useInheritedMediaQuery: widget.useInheritedMediaQuery,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return WidgetsApp(
|
return WidgetsApp(
|
||||||
@ -564,6 +570,7 @@ class _CupertinoAppState extends State<CupertinoApp> {
|
|||||||
shortcuts: widget.shortcuts,
|
shortcuts: widget.shortcuts,
|
||||||
actions: widget.actions,
|
actions: widget.actions,
|
||||||
restorationScopeId: widget.restorationScopeId,
|
restorationScopeId: widget.restorationScopeId,
|
||||||
|
useInheritedMediaQuery: widget.useInheritedMediaQuery,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +200,7 @@ class MaterialApp extends StatefulWidget {
|
|||||||
this.actions,
|
this.actions,
|
||||||
this.restorationScopeId,
|
this.restorationScopeId,
|
||||||
this.scrollBehavior,
|
this.scrollBehavior,
|
||||||
|
this.useInheritedMediaQuery = false,
|
||||||
}) : assert(routes != null),
|
}) : assert(routes != null),
|
||||||
assert(navigatorObservers != null),
|
assert(navigatorObservers != null),
|
||||||
assert(title != null),
|
assert(title != null),
|
||||||
@ -247,6 +248,7 @@ class MaterialApp extends StatefulWidget {
|
|||||||
this.actions,
|
this.actions,
|
||||||
this.restorationScopeId,
|
this.restorationScopeId,
|
||||||
this.scrollBehavior,
|
this.scrollBehavior,
|
||||||
|
this.useInheritedMediaQuery = false,
|
||||||
}) : assert(routeInformationParser != null),
|
}) : assert(routeInformationParser != null),
|
||||||
assert(routerDelegate != null),
|
assert(routerDelegate != null),
|
||||||
assert(title != null),
|
assert(title != null),
|
||||||
@ -665,6 +667,9 @@ class MaterialApp extends StatefulWidget {
|
|||||||
/// * <https://material.io/design/layout/spacing-methods.html>
|
/// * <https://material.io/design/layout/spacing-methods.html>
|
||||||
final bool debugShowMaterialGrid;
|
final bool debugShowMaterialGrid;
|
||||||
|
|
||||||
|
/// {@macro flutter.widgets.widgetsApp.useInheritedMediaQuery}
|
||||||
|
final bool useInheritedMediaQuery;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MaterialApp> createState() => _MaterialAppState();
|
State<MaterialApp> createState() => _MaterialAppState();
|
||||||
|
|
||||||
@ -858,6 +863,7 @@ class _MaterialAppState extends State<MaterialApp> {
|
|||||||
shortcuts: widget.shortcuts,
|
shortcuts: widget.shortcuts,
|
||||||
actions: widget.actions,
|
actions: widget.actions,
|
||||||
restorationScopeId: widget.restorationScopeId,
|
restorationScopeId: widget.restorationScopeId,
|
||||||
|
useInheritedMediaQuery: widget.useInheritedMediaQuery,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -893,6 +899,7 @@ class _MaterialAppState extends State<MaterialApp> {
|
|||||||
shortcuts: widget.shortcuts,
|
shortcuts: widget.shortcuts,
|
||||||
actions: widget.actions,
|
actions: widget.actions,
|
||||||
restorationScopeId: widget.restorationScopeId,
|
restorationScopeId: widget.restorationScopeId,
|
||||||
|
useInheritedMediaQuery: widget.useInheritedMediaQuery,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,6 +236,9 @@ typedef InitialRouteListFactory = List<Route<dynamic>> Function(String initialRo
|
|||||||
/// It is used by both [MaterialApp] and [CupertinoApp] to implement base
|
/// It is used by both [MaterialApp] and [CupertinoApp] to implement base
|
||||||
/// functionality for an app.
|
/// functionality for an app.
|
||||||
///
|
///
|
||||||
|
/// Builds a [MediaQuery] using [MediaQuery.fromWindow]. To use an inherited
|
||||||
|
/// [MediaQuery] instead, set [useInheritedMediaQuery] to true.
|
||||||
|
///
|
||||||
/// Find references to many of the widgets that [WidgetsApp] wraps in the "See
|
/// Find references to many of the widgets that [WidgetsApp] wraps in the "See
|
||||||
/// also" section.
|
/// also" section.
|
||||||
///
|
///
|
||||||
@ -247,6 +250,8 @@ typedef InitialRouteListFactory = List<Route<dynamic>> Function(String initialRo
|
|||||||
/// without an explicit style.
|
/// without an explicit style.
|
||||||
/// * [MediaQuery], which establishes a subtree in which media queries resolve
|
/// * [MediaQuery], which establishes a subtree in which media queries resolve
|
||||||
/// to a [MediaQueryData].
|
/// to a [MediaQueryData].
|
||||||
|
/// * [MediaQuery.fromWindow], which builds a [MediaQuery] with data derived
|
||||||
|
/// from [WidgetsBinding.window].
|
||||||
/// * [Localizations], which defines the [Locale] for its `child`.
|
/// * [Localizations], which defines the [Locale] for its `child`.
|
||||||
/// * [Title], a widget that describes this app in the operating system.
|
/// * [Title], a widget that describes this app in the operating system.
|
||||||
/// * [Navigator], a widget that manages a set of child widgets with a stack
|
/// * [Navigator], a widget that manages a set of child widgets with a stack
|
||||||
@ -327,6 +332,7 @@ class WidgetsApp extends StatefulWidget {
|
|||||||
this.shortcuts,
|
this.shortcuts,
|
||||||
this.actions,
|
this.actions,
|
||||||
this.restorationScopeId,
|
this.restorationScopeId,
|
||||||
|
this.useInheritedMediaQuery = false,
|
||||||
}) : assert(navigatorObservers != null),
|
}) : assert(navigatorObservers != null),
|
||||||
assert(routes != null),
|
assert(routes != null),
|
||||||
assert(
|
assert(
|
||||||
@ -423,6 +429,7 @@ class WidgetsApp extends StatefulWidget {
|
|||||||
this.shortcuts,
|
this.shortcuts,
|
||||||
this.actions,
|
this.actions,
|
||||||
this.restorationScopeId,
|
this.restorationScopeId,
|
||||||
|
this.useInheritedMediaQuery = false,
|
||||||
}) : assert(
|
}) : assert(
|
||||||
routeInformationParser != null &&
|
routeInformationParser != null &&
|
||||||
routerDelegate != null,
|
routerDelegate != null,
|
||||||
@ -1111,6 +1118,14 @@ class WidgetsApp extends StatefulWidget {
|
|||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
final String? restorationScopeId;
|
final String? restorationScopeId;
|
||||||
|
|
||||||
|
/// {@template flutter.widgets.widgetsApp.useInheritedMediaQuery}
|
||||||
|
/// If true, an inherited MediaQuery will be used. If one is not available,
|
||||||
|
/// or this is false, one will be built from the window.
|
||||||
|
///
|
||||||
|
/// Cannot be null, defaults to false.
|
||||||
|
/// {@endtemplate}
|
||||||
|
final bool useInheritedMediaQuery;
|
||||||
|
|
||||||
/// If true, forces the performance overlay to be visible in all instances.
|
/// If true, forces the performance overlay to be visible in all instances.
|
||||||
///
|
///
|
||||||
/// Used by the `showPerformanceOverlay` observatory extension.
|
/// Used by the `showPerformanceOverlay` observatory extension.
|
||||||
@ -1635,6 +1650,19 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
assert(_debugCheckLocalizations(appLocale));
|
assert(_debugCheckLocalizations(appLocale));
|
||||||
|
|
||||||
|
Widget child = Localizations(
|
||||||
|
locale: appLocale,
|
||||||
|
delegates: _localizationsDelegates.toList(),
|
||||||
|
child: title,
|
||||||
|
);
|
||||||
|
|
||||||
|
final MediaQueryData? data = MediaQuery.maybeOf(context);
|
||||||
|
if (!widget.useInheritedMediaQuery || data == null) {
|
||||||
|
child = MediaQuery.fromWindow(
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return RootRestorationScope(
|
return RootRestorationScope(
|
||||||
restorationId: widget.restorationScopeId,
|
restorationId: widget.restorationScopeId,
|
||||||
child: Shortcuts(
|
child: Shortcuts(
|
||||||
@ -1648,13 +1676,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
|
|||||||
child: DefaultTextEditingActions(
|
child: DefaultTextEditingActions(
|
||||||
child: FocusTraversalGroup(
|
child: FocusTraversalGroup(
|
||||||
policy: ReadingOrderTraversalPolicy(),
|
policy: ReadingOrderTraversalPolicy(),
|
||||||
child: _MediaQueryFromWindow(
|
child: child,
|
||||||
child: Localizations(
|
|
||||||
locale: appLocale,
|
|
||||||
delegates: _localizationsDelegates.toList(),
|
|
||||||
child: title,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1663,81 +1685,3 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds [MediaQuery] from `window` by listening to [WidgetsBinding].
|
|
||||||
///
|
|
||||||
/// It is performed in a standalone widget to rebuild **only** [MediaQuery] and
|
|
||||||
/// its dependents when `window` changes, instead of rebuilding the entire widget tree.
|
|
||||||
class _MediaQueryFromWindow extends StatefulWidget {
|
|
||||||
const _MediaQueryFromWindow({Key? key, required this.child}) : super(key: key);
|
|
||||||
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
@override
|
|
||||||
_MediaQueryFromWindowsState createState() => _MediaQueryFromWindowsState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MediaQueryFromWindowsState extends State<_MediaQueryFromWindow> with WidgetsBindingObserver {
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
WidgetsBinding.instance!.addObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ACCESSIBILITY
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeAccessibilityFeatures() {
|
|
||||||
setState(() {
|
|
||||||
// The properties of window have changed. We use them in our build
|
|
||||||
// function, so we need setState(), but we don't cache anything locally.
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// METRICS
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeMetrics() {
|
|
||||||
setState(() {
|
|
||||||
// The properties of window have changed. We use them in our build
|
|
||||||
// function, so we need setState(), but we don't cache anything locally.
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeTextScaleFactor() {
|
|
||||||
setState(() {
|
|
||||||
// The textScaleFactor property of window has changed. We reference
|
|
||||||
// window in our build function, so we need to call setState(), but
|
|
||||||
// we don't need to cache anything locally.
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// RENDERING
|
|
||||||
@override
|
|
||||||
void didChangePlatformBrightness() {
|
|
||||||
setState(() {
|
|
||||||
// The platformBrightness property of window has changed. We reference
|
|
||||||
// window in our build function, so we need to call setState(), but
|
|
||||||
// we don't need to cache anything locally.
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance!.window);
|
|
||||||
if (!kReleaseMode) {
|
|
||||||
data = data.copyWith(platformBrightness: debugBrightnessOverride);
|
|
||||||
}
|
|
||||||
return MediaQuery(
|
|
||||||
data: data,
|
|
||||||
child: widget.child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
WidgetsBinding.instance!.removeObserver(this);
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -9,6 +9,7 @@ import 'dart:ui' show Brightness;
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'basic.dart';
|
import 'basic.dart';
|
||||||
|
import 'binding.dart';
|
||||||
import 'debug.dart';
|
import 'debug.dart';
|
||||||
import 'framework.dart';
|
import 'framework.dart';
|
||||||
|
|
||||||
@ -787,6 +788,28 @@ class MediaQuery extends InheritedWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides a [MediaQuery] which is built and updated using the latest
|
||||||
|
/// [WidgetsBinding.window] values.
|
||||||
|
///
|
||||||
|
/// The [MediaQuery] is wrapped in a separate widget to ensure that only it
|
||||||
|
/// and its dependents are updated when `window` changes, instead of
|
||||||
|
/// rebuilding the whole widget tree.
|
||||||
|
///
|
||||||
|
/// This should be inserted into the widget tree when the [MediaQuery] view
|
||||||
|
/// padding is consumed by a widget in such a way that the view padding is no
|
||||||
|
/// longer exposed to the widget's descendants or siblings.
|
||||||
|
///
|
||||||
|
/// The [child] argument is required and must not be null.
|
||||||
|
static Widget fromWindow({
|
||||||
|
Key? key,
|
||||||
|
required Widget child,
|
||||||
|
}) {
|
||||||
|
return _MediaQueryFromWindow(
|
||||||
|
key: key,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Contains information about the current media.
|
/// Contains information about the current media.
|
||||||
///
|
///
|
||||||
/// For example, the [MediaQueryData.size] property contains the width and
|
/// For example, the [MediaQueryData.size] property contains the width and
|
||||||
@ -922,3 +945,100 @@ enum NavigationMode {
|
|||||||
/// focus (although they remain disabled) when traversed.
|
/// focus (although they remain disabled) when traversed.
|
||||||
directional,
|
directional,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides a [MediaQuery] which is built and updated using the latest
|
||||||
|
/// [WidgetsBinding.window] values.
|
||||||
|
///
|
||||||
|
/// Receives `window` updates by listening to [WidgetsBinding].
|
||||||
|
///
|
||||||
|
/// The standalone widget ensures that it rebuilds **only** [MediaQuery] and
|
||||||
|
/// its dependents when `window` changes, instead of rebuilding the entire
|
||||||
|
/// widget tree.
|
||||||
|
///
|
||||||
|
/// It is used by [WidgetsApp] if no other [MediaQuery] is available above it.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [MediaQuery], which establishes a subtree in which media queries resolve
|
||||||
|
/// to a [MediaQueryData].
|
||||||
|
class _MediaQueryFromWindow extends StatefulWidget {
|
||||||
|
/// Creates a [_MediaQueryFromWindow] that provides a [MediaQuery] to its
|
||||||
|
/// descendants using the `window` to keep [MediaQueryData] up to date.
|
||||||
|
///
|
||||||
|
/// The [child] must not be null.
|
||||||
|
const _MediaQueryFromWindow({
|
||||||
|
Key? key,
|
||||||
|
required this.child,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_MediaQueryFromWindow> createState() => _MediaQueryFromWindowState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MediaQueryFromWindowState extends State<_MediaQueryFromWindow> with WidgetsBindingObserver {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
WidgetsBinding.instance!.addObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACCESSIBILITY
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeAccessibilityFeatures() {
|
||||||
|
setState(() {
|
||||||
|
// The properties of window have changed. We use them in our build
|
||||||
|
// function, so we need setState(), but we don't cache anything locally.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// METRICS
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeMetrics() {
|
||||||
|
setState(() {
|
||||||
|
// The properties of window have changed. We use them in our build
|
||||||
|
// function, so we need setState(), but we don't cache anything locally.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeTextScaleFactor() {
|
||||||
|
setState(() {
|
||||||
|
// The textScaleFactor property of window has changed. We reference
|
||||||
|
// window in our build function, so we need to call setState(), but
|
||||||
|
// we don't need to cache anything locally.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// RENDERING
|
||||||
|
@override
|
||||||
|
void didChangePlatformBrightness() {
|
||||||
|
setState(() {
|
||||||
|
// The platformBrightness property of window has changed. We reference
|
||||||
|
// window in our build function, so we need to call setState(), but
|
||||||
|
// we don't need to cache anything locally.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
MediaQueryData data = MediaQueryData.fromWindow(WidgetsBinding.instance!.window);
|
||||||
|
if (!kReleaseMode) {
|
||||||
|
data = data.copyWith(platformBrightness: debugBrightnessOverride);
|
||||||
|
}
|
||||||
|
return MediaQuery(
|
||||||
|
data: data,
|
||||||
|
child: widget.child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
WidgetsBinding.instance!.removeObserver(this);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -208,6 +208,26 @@ void main() {
|
|||||||
expect(scrollBehavior.runtimeType, MockScrollBehavior);
|
expect(scrollBehavior.runtimeType, MockScrollBehavior);
|
||||||
expect(scrollBehavior.getScrollPhysics(capturedContext).runtimeType, NeverScrollableScrollPhysics);
|
expect(scrollBehavior.getScrollPhysics(capturedContext).runtimeType, NeverScrollableScrollPhysics);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('When `useInheritedMediaQuery` is true an existing MediaQuery is used if one is available', (WidgetTester tester) async {
|
||||||
|
late BuildContext capturedContext;
|
||||||
|
final UniqueKey uniqueKey = UniqueKey();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MediaQuery(
|
||||||
|
key: uniqueKey,
|
||||||
|
data: const MediaQueryData(),
|
||||||
|
child: CupertinoApp(
|
||||||
|
useInheritedMediaQuery: true,
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
capturedContext = context;
|
||||||
|
return const Placeholder();
|
||||||
|
},
|
||||||
|
color: const Color(0xFF123456),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(capturedContext.dependOnInheritedWidgetOfExactType<MediaQuery>()?.key, uniqueKey);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockScrollBehavior extends ScrollBehavior {
|
class MockScrollBehavior extends ScrollBehavior {
|
||||||
|
@ -1069,6 +1069,26 @@ void main() {
|
|||||||
expect(scrollBehavior.runtimeType, MockScrollBehavior);
|
expect(scrollBehavior.runtimeType, MockScrollBehavior);
|
||||||
expect(scrollBehavior.getScrollPhysics(capturedContext).runtimeType, NeverScrollableScrollPhysics);
|
expect(scrollBehavior.getScrollPhysics(capturedContext).runtimeType, NeverScrollableScrollPhysics);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('When `useInheritedMediaQuery` is true an existing MediaQuery is used if one is available', (WidgetTester tester) async {
|
||||||
|
late BuildContext capturedContext;
|
||||||
|
final UniqueKey uniqueKey = UniqueKey();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MediaQuery(
|
||||||
|
key: uniqueKey,
|
||||||
|
data: const MediaQueryData(),
|
||||||
|
child: MaterialApp(
|
||||||
|
useInheritedMediaQuery: true,
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
capturedContext = context;
|
||||||
|
return const Placeholder();
|
||||||
|
},
|
||||||
|
color: const Color(0xFF123456),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(capturedContext.dependOnInheritedWidgetOfExactType<MediaQuery>()?.key, uniqueKey);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockScrollBehavior extends ScrollBehavior {
|
class MockScrollBehavior extends ScrollBehavior {
|
||||||
|
@ -455,6 +455,56 @@ void main() {
|
|||||||
const Locale('zh'),
|
const Locale('zh'),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('WidgetsApp creates a MediaQuery if `useInheritedMediaQuery` is set to false', (WidgetTester tester) async {
|
||||||
|
late BuildContext capturedContext;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
WidgetsApp(
|
||||||
|
useInheritedMediaQuery: false,
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
capturedContext = context;
|
||||||
|
return const Placeholder();
|
||||||
|
},
|
||||||
|
color: const Color(0xFF123456),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(MediaQuery.of(capturedContext), isNotNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('WidgetsApp does not create MediaQuery if `useInheritedMediaQuery` is set to true and one is available', (WidgetTester tester) async {
|
||||||
|
late BuildContext capturedContext;
|
||||||
|
final UniqueKey uniqueKey = UniqueKey();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MediaQuery(
|
||||||
|
key: uniqueKey,
|
||||||
|
data: const MediaQueryData(),
|
||||||
|
child: WidgetsApp(
|
||||||
|
useInheritedMediaQuery: true,
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
capturedContext = context;
|
||||||
|
return const Placeholder();
|
||||||
|
},
|
||||||
|
color: const Color(0xFF123456),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(capturedContext.dependOnInheritedWidgetOfExactType<MediaQuery>()?.key, uniqueKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('WidgetsApp does create a MediaQuery if `useInheritedMediaQuery` is set to true and none is available', (WidgetTester tester) async {
|
||||||
|
late BuildContext capturedContext;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
WidgetsApp(
|
||||||
|
useInheritedMediaQuery: true,
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
capturedContext = context;
|
||||||
|
return const Placeholder();
|
||||||
|
},
|
||||||
|
color: const Color(0xFF123456),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(MediaQuery.of(capturedContext), isNotNull);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef SimpleRouterDelegateBuilder = Widget Function(BuildContext, RouteInformation);
|
typedef SimpleRouterDelegateBuilder = Widget Function(BuildContext, RouteInformation);
|
||||||
|
@ -627,4 +627,49 @@ void main() {
|
|||||||
expect(outsideBoldTextOverride, false);
|
expect(outsideBoldTextOverride, false);
|
||||||
expect(insideBoldTextOverride, true);
|
expect(insideBoldTextOverride, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('MediaQuery.fromWindow creates a MediaQuery', (WidgetTester tester) async {
|
||||||
|
bool hasMediaQueryAsParentOutside = false;
|
||||||
|
bool hasMediaQueryAsParentInside = false;
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Builder(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
hasMediaQueryAsParentOutside =
|
||||||
|
context.findAncestorWidgetOfExactType<MediaQuery>() != null;
|
||||||
|
return MediaQuery.fromWindow(
|
||||||
|
child: Builder(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
hasMediaQueryAsParentInside =
|
||||||
|
context.findAncestorWidgetOfExactType<MediaQuery>() != null;
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(hasMediaQueryAsParentOutside, false);
|
||||||
|
expect(hasMediaQueryAsParentInside, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('MediaQueryData.fromWindow is created using window values', (WidgetTester tester)
|
||||||
|
async {
|
||||||
|
final MediaQueryData windowData = MediaQueryData.fromWindow(WidgetsBinding.instance!.window);
|
||||||
|
late MediaQueryData fromWindowData;
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MediaQuery.fromWindow(
|
||||||
|
child: Builder(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
fromWindowData = MediaQuery.of(context);
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(windowData, equals(fromWindowData));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user