1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | /// @docImport 'package:flutter/cupertino.dart'; |
6 | /// @docImport 'package:flutter/material.dart'; |
7 | /// @docImport 'package:flutter/services.dart'; |
8 | /// |
9 | /// @docImport 'app.dart'; |
10 | /// @docImport 'display_feature_sub_screen.dart'; |
11 | /// @docImport 'overlay.dart'; |
12 | /// @docImport 'safe_area.dart'; |
13 | /// @docImport 'system_context_menu.dart'; |
14 | /// @docImport 'view.dart'; |
15 | library; |
16 | |
17 | import 'dart:math' as math; |
18 | import 'dart:ui' as ui; |
19 | |
20 | import 'package:flutter/foundation.dart'; |
21 | import 'package:flutter/gestures.dart'; |
22 | |
23 | import 'basic.dart'; |
24 | import 'binding.dart'; |
25 | import 'debug.dart'; |
26 | import 'framework.dart'; |
27 | import 'inherited_model.dart'; |
28 | |
29 | // Examples can assume: |
30 | // late BuildContext context; |
31 | |
32 | /// Whether in portrait or landscape. |
33 | enum Orientation { |
34 | /// Taller than wide. |
35 | portrait, |
36 | |
37 | /// Wider than tall. |
38 | landscape |
39 | } |
40 | |
41 | /// Specifies a part of MediaQueryData to depend on. |
42 | /// |
43 | /// [MediaQuery] contains a large number of related properties. Widgets frequently |
44 | /// depend on only a few of these attributes. For example, a widget that needs to |
45 | /// rebuild when the [MediaQueryData.textScaler] changes does not need to be |
46 | /// notified when the [MediaQueryData.size] changes. Specifying an aspect avoids |
47 | /// unnecessary rebuilds. |
48 | enum _MediaQueryAspect { |
49 | /// Specifies the aspect corresponding to [MediaQueryData.size]. |
50 | size, |
51 | /// Specifies the aspect corresponding to [MediaQueryData.orientation]. |
52 | orientation, |
53 | /// Specifies the aspect corresponding to [MediaQueryData.devicePixelRatio]. |
54 | devicePixelRatio, |
55 | /// Specifies the aspect corresponding to [MediaQueryData.textScaleFactor]. |
56 | textScaleFactor, |
57 | /// Specifies the aspect corresponding to [MediaQueryData.textScaler]. |
58 | textScaler, |
59 | /// Specifies the aspect corresponding to [MediaQueryData.platformBrightness]. |
60 | platformBrightness, |
61 | /// Specifies the aspect corresponding to [MediaQueryData.padding]. |
62 | padding, |
63 | /// Specifies the aspect corresponding to [MediaQueryData.viewInsets]. |
64 | viewInsets, |
65 | /// Specifies the aspect corresponding to [MediaQueryData.systemGestureInsets]. |
66 | systemGestureInsets, |
67 | /// Specifies the aspect corresponding to [MediaQueryData.viewPadding]. |
68 | viewPadding, |
69 | /// Specifies the aspect corresponding to [MediaQueryData.alwaysUse24HourFormat]. |
70 | alwaysUse24HourFormat, |
71 | /// Specifies the aspect corresponding to [MediaQueryData.accessibleNavigation]. |
72 | accessibleNavigation, |
73 | /// Specifies the aspect corresponding to [MediaQueryData.invertColors]. |
74 | invertColors, |
75 | /// Specifies the aspect corresponding to [MediaQueryData.highContrast]. |
76 | highContrast, |
77 | /// Specifies the aspect corresponding to [MediaQueryData.onOffSwitchLabels]. |
78 | onOffSwitchLabels, |
79 | /// Specifies the aspect corresponding to [MediaQueryData.disableAnimations]. |
80 | disableAnimations, |
81 | /// Specifies the aspect corresponding to [MediaQueryData.boldText]. |
82 | boldText, |
83 | /// Specifies the aspect corresponding to [MediaQueryData.navigationMode]. |
84 | navigationMode, |
85 | /// Specifies the aspect corresponding to [MediaQueryData.gestureSettings]. |
86 | gestureSettings, |
87 | /// Specifies the aspect corresponding to [MediaQueryData.displayFeatures]. |
88 | displayFeatures, |
89 | /// Specifies the aspect corresponding to [MediaQueryData.supportsShowingSystemContextMenu]. |
90 | supportsShowingSystemContextMenu, |
91 | } |
92 | |
93 | /// Information about a piece of media (e.g., a window). |
94 | /// |
95 | /// For example, the [MediaQueryData.size] property contains the width and |
96 | /// height of the current window. |
97 | /// |
98 | /// To obtain individual attributes in a [MediaQueryData], prefer to use the |
99 | /// attribute-specific functions of [MediaQuery] over obtaining the entire |
100 | /// [MediaQueryData] and accessing its members. |
101 | /// {@macro flutter.widgets.media_query.MediaQuery.useSpecific} |
102 | /// |
103 | /// To obtain the entire current [MediaQueryData] for a given [BuildContext], |
104 | /// use the [MediaQuery.of] function. This can be useful if you are going to use |
105 | /// [copyWith] to replace the [MediaQueryData] with one with an updated |
106 | /// property. |
107 | /// |
108 | /// ## Insets and Padding |
109 | /// |
110 | /// ![A diagram of padding, viewInsets, and viewPadding in correlation with each |
111 | /// other](https://flutter.github.io/assets-for-api-docs/assets/widgets/media_query.png) |
112 | /// |
113 | /// This diagram illustrates how [padding] relates to [viewPadding] and |
114 | /// [viewInsets], shown here in its simplest configuration, as the difference |
115 | /// between the two. In cases when the viewInsets exceed the viewPadding, like |
116 | /// when a software keyboard is shown below, padding goes to zero rather than a |
117 | /// negative value. Therefore, padding is calculated by taking |
118 | /// `max(0.0, viewPadding - viewInsets)`. |
119 | /// |
120 | /// {@animation 300 300 https://flutter.github.io/assets-for-api-docs/assets/widgets/window_padding.mp4} |
121 | /// |
122 | /// In this diagram, the black areas represent system UI that the app cannot |
123 | /// draw over. The red area represents view padding that the application may not |
124 | /// be able to detect gestures in and may not want to draw in. The grey area |
125 | /// represents the system keyboard, which can cover over the bottom view padding |
126 | /// when visible. |
127 | /// |
128 | /// MediaQueryData includes three [EdgeInsets] values: |
129 | /// [padding], [viewPadding], and [viewInsets]. These values reflect the |
130 | /// configuration of the device and are used and optionally consumed by widgets |
131 | /// that position content within these insets. The padding value defines areas |
132 | /// that might not be completely visible, like the display "notch" on the iPhone |
133 | /// X. The viewInsets value defines areas that aren't visible at all, typically |
134 | /// because they're obscured by the device's keyboard. Similar to viewInsets, |
135 | /// viewPadding does not differentiate padding in areas that may be obscured. |
136 | /// For example, by using the viewPadding property, padding would defer to the |
137 | /// iPhone "safe area" regardless of whether a keyboard is showing. |
138 | /// |
139 | /// {@youtube 560 315 https://www.youtube.com/watch?v=ceCo8U0XHqw} |
140 | /// |
141 | /// The viewInsets and viewPadding are independent values, they're |
142 | /// measured from the edges of the MediaQuery widget's bounds. Together they |
143 | /// inform the [padding] property. The bounds of the top level MediaQuery |
144 | /// created by [WidgetsApp] are the same as the window that contains the app. |
145 | /// |
146 | /// Widgets whose layouts consume space defined by [viewInsets], [viewPadding], |
147 | /// or [padding] should enclose their children in secondary MediaQuery |
148 | /// widgets that reduce those properties by the same amount. |
149 | /// The [removePadding], [removeViewPadding], and [removeViewInsets] methods are |
150 | /// useful for this. |
151 | /// |
152 | /// See also: |
153 | /// |
154 | /// * [Scaffold], [SafeArea], [CupertinoTabScaffold], and |
155 | /// [CupertinoPageScaffold], all of which are informed by [padding], |
156 | /// [viewPadding], and [viewInsets]. |
157 | @immutable |
158 | class MediaQueryData { |
159 | /// Creates data for a media query with explicit values. |
160 | /// |
161 | /// In a typical application, calling this constructor directly is rarely |
162 | /// needed. Consider using [MediaQueryData.fromView] to create data based on a |
163 | /// [dart:ui.FlutterView], or [MediaQueryData.copyWith] to create a new copy |
164 | /// of [MediaQueryData] with updated properties from a base [MediaQueryData]. |
165 | const MediaQueryData({ |
166 | this.size = Size.zero, |
167 | this.devicePixelRatio = 1.0, |
168 | @Deprecated( |
169 | 'Use textScaler instead. ' |
170 | 'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. ' |
171 | 'This feature was deprecated after v3.12.0-2.0.pre.' , |
172 | ) |
173 | double textScaleFactor = 1.0, |
174 | TextScaler textScaler = _kUnspecifiedTextScaler, |
175 | this.platformBrightness = Brightness.light, |
176 | this.padding = EdgeInsets.zero, |
177 | this.viewInsets = EdgeInsets.zero, |
178 | this.systemGestureInsets = EdgeInsets.zero, |
179 | this.viewPadding = EdgeInsets.zero, |
180 | this.alwaysUse24HourFormat = false, |
181 | this.accessibleNavigation = false, |
182 | this.invertColors = false, |
183 | this.highContrast = false, |
184 | this.onOffSwitchLabels = false, |
185 | this.disableAnimations = false, |
186 | this.boldText = false, |
187 | this.navigationMode = NavigationMode.traditional, |
188 | this.gestureSettings = const DeviceGestureSettings(touchSlop: kTouchSlop), |
189 | this.displayFeatures = const <ui.DisplayFeature>[], |
190 | this.supportsShowingSystemContextMenu = false, |
191 | }) : _textScaleFactor = textScaleFactor, |
192 | _textScaler = textScaler, |
193 | assert( |
194 | identical(textScaler, _kUnspecifiedTextScaler) || textScaleFactor == 1.0, |
195 | 'textScaleFactor is deprecated and cannot be specified when textScaler is specified.' , |
196 | ); |
197 | |
198 | /// Deprecated. Use [MediaQueryData.fromView] instead. |
199 | /// |
200 | /// This constructor was operating on a single window assumption. In |
201 | /// preparation for Flutter's upcoming multi-window support, it has been |
202 | /// deprecated. |
203 | @Deprecated( |
204 | 'Use MediaQueryData.fromView instead. ' |
205 | 'This constructor was deprecated in preparation for the upcoming multi-window support. ' |
206 | 'This feature was deprecated after v3.7.0-32.0.pre.' |
207 | ) |
208 | factory MediaQueryData.fromWindow(ui.FlutterView window) = MediaQueryData.fromView; |
209 | |
210 | /// Creates data for a [MediaQuery] based on the given `view`. |
211 | /// |
212 | /// If provided, the `platformData` is used to fill in the platform-specific |
213 | /// aspects of the newly created [MediaQueryData]. If `platformData` is null, |
214 | /// the `view`'s [PlatformDispatcher] is consulted to construct the |
215 | /// platform-specific data. |
216 | /// |
217 | /// Data which is exposed directly on the [FlutterView] is considered |
218 | /// view-specific. Data which is only exposed via the |
219 | /// [FlutterView.platformDispatcher] property is considered platform-specific. |
220 | /// |
221 | /// Callers of this method should ensure that they also register for |
222 | /// notifications so that the [MediaQueryData] can be updated when any data |
223 | /// used to construct it changes. Notifications to consider are: |
224 | /// |
225 | /// * [WidgetsBindingObserver.didChangeMetrics] or |
226 | /// [dart:ui.PlatformDispatcher.onMetricsChanged], |
227 | /// * [WidgetsBindingObserver.didChangeAccessibilityFeatures] or |
228 | /// [dart:ui.PlatformDispatcher.onAccessibilityFeaturesChanged], |
229 | /// * [WidgetsBindingObserver.didChangeTextScaleFactor] or |
230 | /// [dart:ui.PlatformDispatcher.onTextScaleFactorChanged], |
231 | /// * [WidgetsBindingObserver.didChangePlatformBrightness] or |
232 | /// [dart:ui.PlatformDispatcher.onPlatformBrightnessChanged]. |
233 | /// |
234 | /// The last three notifications are only relevant if no `platformData` is |
235 | /// provided. If `platformData` is provided, callers should ensure to call |
236 | /// this method again when it changes to keep the constructed [MediaQueryData] |
237 | /// updated. |
238 | /// |
239 | /// In general, [MediaQuery.of], and its associated "...Of" methods, are the |
240 | /// appropriate way to obtain [MediaQueryData] from a widget. This `fromView` |
241 | /// constructor is primarily for use in the implementation of the framework |
242 | /// itself. |
243 | /// |
244 | /// See also: |
245 | /// |
246 | /// * [MediaQuery.fromView], which constructs [MediaQueryData] from a provided |
247 | /// [FlutterView], makes it available to descendant widgets, and sets up |
248 | /// the appropriate notification listeners to keep the data updated. |
249 | MediaQueryData.fromView(ui.FlutterView view, {MediaQueryData? platformData}) |
250 | : size = view.physicalSize / view.devicePixelRatio, |
251 | devicePixelRatio = view.devicePixelRatio, |
252 | _textScaleFactor = 1.0, // _textScaler is the source of truth. |
253 | _textScaler = _textScalerFromView(view, platformData), |
254 | platformBrightness = platformData?.platformBrightness ?? view.platformDispatcher.platformBrightness, |
255 | padding = EdgeInsets.fromViewPadding(view.padding, view.devicePixelRatio), |
256 | viewPadding = EdgeInsets.fromViewPadding(view.viewPadding, view.devicePixelRatio), |
257 | viewInsets = EdgeInsets.fromViewPadding(view.viewInsets, view.devicePixelRatio), |
258 | systemGestureInsets = EdgeInsets.fromViewPadding(view.systemGestureInsets, view.devicePixelRatio), |
259 | accessibleNavigation = platformData?.accessibleNavigation ?? view.platformDispatcher.accessibilityFeatures.accessibleNavigation, |
260 | invertColors = platformData?.invertColors ?? view.platformDispatcher.accessibilityFeatures.invertColors, |
261 | disableAnimations = platformData?.disableAnimations ?? view.platformDispatcher.accessibilityFeatures.disableAnimations, |
262 | boldText = platformData?.boldText ?? view.platformDispatcher.accessibilityFeatures.boldText, |
263 | highContrast = platformData?.highContrast ?? view.platformDispatcher.accessibilityFeatures.highContrast, |
264 | onOffSwitchLabels = platformData?.onOffSwitchLabels ?? view.platformDispatcher.accessibilityFeatures.onOffSwitchLabels, |
265 | alwaysUse24HourFormat = platformData?.alwaysUse24HourFormat ?? view.platformDispatcher.alwaysUse24HourFormat, |
266 | navigationMode = platformData?.navigationMode ?? NavigationMode.traditional, |
267 | gestureSettings = DeviceGestureSettings.fromView(view), |
268 | displayFeatures = view.displayFeatures, |
269 | supportsShowingSystemContextMenu = platformData?.supportsShowingSystemContextMenu ?? view.platformDispatcher.supportsShowingSystemContextMenu; |
270 | |
271 | static TextScaler _textScalerFromView(ui.FlutterView view, MediaQueryData? platformData) { |
272 | final double scaleFactor = platformData?.textScaleFactor ?? view.platformDispatcher.textScaleFactor; |
273 | return scaleFactor == 1.0 ? TextScaler.noScaling : TextScaler.linear(scaleFactor); |
274 | } |
275 | |
276 | /// The size of the media in logical pixels (e.g, the size of the screen). |
277 | /// |
278 | /// Logical pixels are roughly the same visual size across devices. Physical |
279 | /// pixels are the size of the actual hardware pixels on the device. The |
280 | /// number of physical pixels per logical pixel is described by the |
281 | /// [devicePixelRatio]. |
282 | /// |
283 | /// Prefer using [MediaQuery.sizeOf] over [MediaQuery.of]`.size` to get the |
284 | /// size, since the former will only notify of changes in [size], while the |
285 | /// latter will notify for all [MediaQueryData] changes. |
286 | /// |
287 | /// For widgets drawn in an [Overlay], do not assume that the size of the |
288 | /// [Overlay] is the size of the [MediaQuery]'s size. Nested overlays can have |
289 | /// different sizes. |
290 | /// |
291 | /// ## Troubleshooting |
292 | /// |
293 | /// It is considered bad practice to cache and later use the size returned by |
294 | /// `MediaQuery.sizeOf(context)`. It will make the application non-responsive |
295 | /// and might lead to unexpected behaviors. |
296 | /// |
297 | /// For instance, during startup, especially in release mode, the first |
298 | /// returned size might be [Size.zero]. The size will be updated when the |
299 | /// native platform reports the actual resolution. Using [MediaQuery.sizeOf] |
300 | /// will ensure that when the size changes, any widgets depending on the size |
301 | /// are automatically rebuilt. |
302 | /// |
303 | /// See the article on [Creating responsive and adaptive |
304 | /// apps](https://docs.flutter.dev/ui/adaptive-responsive) |
305 | /// for an introduction. |
306 | /// |
307 | /// See also: |
308 | /// |
309 | /// * [FlutterView.physicalSize], which returns the size of the view in physical pixels. |
310 | /// * [FlutterView.display], which returns reports display information like size, and refresh rate. |
311 | /// * [MediaQuery.sizeOf], a method to find and depend on the size defined for |
312 | /// a [BuildContext]. |
313 | final Size size; |
314 | |
315 | /// The number of device pixels for each logical pixel. This number might not |
316 | /// be a power of two. Indeed, it might not even be an integer. For example, |
317 | /// the Nexus 6 has a device pixel ratio of 3.5. |
318 | final double devicePixelRatio; |
319 | |
320 | /// Deprecated. Will be removed in a future version of Flutter. Use |
321 | /// [textScaler] instead. |
322 | /// |
323 | /// The number of font pixels for each logical pixel. |
324 | /// |
325 | /// For example, if the text scale factor is 1.5, text will be 50% larger than |
326 | /// the specified font size. |
327 | /// |
328 | /// See also: |
329 | /// |
330 | /// * [MediaQuery.textScaleFactorOf], a method to find and depend on the |
331 | /// textScaleFactor defined for a [BuildContext]. |
332 | @Deprecated( |
333 | 'Use textScaler instead. ' |
334 | 'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. ' |
335 | 'This feature was deprecated after v3.12.0-2.0.pre.' , |
336 | ) |
337 | double get textScaleFactor => textScaler.textScaleFactor; |
338 | // TODO(LongCatIsLooong): remove this after textScaleFactor is removed. To |
339 | // maintain backward compatibility and also keep the const constructor this |
340 | // has to be kept as a private field. |
341 | // https://github.com/flutter/flutter/issues/128825 |
342 | final double _textScaleFactor; |
343 | |
344 | /// The font scaling strategy to use for laying out textual contents. |
345 | /// |
346 | /// If this [MediaQueryData] is created by the [MediaQueryData.fromView] |
347 | /// constructor, this property reflects the platform's preferred text scaling |
348 | /// strategy, and may change as the user changes the scaling factor in the |
349 | /// operating system's accessibility settings. |
350 | /// |
351 | /// See also: |
352 | /// |
353 | /// * [MediaQuery.textScalerOf], a method to find and depend on the |
354 | /// [textScaler] defined for a [BuildContext]. |
355 | /// * [TextPainter], a class that lays out and paints text. |
356 | TextScaler get textScaler { |
357 | // The constructor was called with an explicitly specified textScaler value, |
358 | // we assume the caller is migrated and ignore _textScaleFactor. |
359 | if (!identical(_kUnspecifiedTextScaler, _textScaler)) { |
360 | return _textScaler; |
361 | } |
362 | return _textScaleFactor == 1.0 |
363 | // textScaleFactor and textScaler from the constructor are consistent. |
364 | ? TextScaler.noScaling |
365 | // The constructor was called with an explicitly specified textScaleFactor, |
366 | // we assume the caller is unmigrated and ignore _textScaler. |
367 | : TextScaler.linear(_textScaleFactor); |
368 | } |
369 | final TextScaler _textScaler; |
370 | |
371 | /// The current brightness mode of the host platform. |
372 | /// |
373 | /// For example, starting in Android Pie, battery saver mode asks all apps to |
374 | /// render in a "dark mode". |
375 | /// |
376 | /// Not all platforms necessarily support a concept of brightness mode. Those |
377 | /// platforms will report [Brightness.light] in this property. |
378 | /// |
379 | /// See also: |
380 | /// |
381 | /// * [MediaQuery.platformBrightnessOf], a method to find and depend on the |
382 | /// platformBrightness defined for a [BuildContext]. |
383 | final Brightness platformBrightness; |
384 | |
385 | /// The parts of the display that are completely obscured by system UI, |
386 | /// typically by the device's keyboard. |
387 | /// |
388 | /// When a mobile device's keyboard is visible `viewInsets.bottom` |
389 | /// corresponds to the top of the keyboard. |
390 | /// |
391 | /// This value is independent of the [padding] and [viewPadding]. viewPadding |
392 | /// is measured from the edges of the [MediaQuery] widget's bounds. Padding is |
393 | /// calculated based on the viewPadding and viewInsets. The bounds of the top |
394 | /// level MediaQuery created by [WidgetsApp] are the same as the window |
395 | /// (often the mobile device screen) that contains the app. |
396 | /// |
397 | /// {@youtube 560 315 https://www.youtube.com/watch?v=ceCo8U0XHqw} |
398 | /// |
399 | /// See also: |
400 | /// |
401 | /// * [FlutterView], which provides some additional detail about this property |
402 | /// and how it relates to [padding] and [viewPadding]. |
403 | final EdgeInsets viewInsets; |
404 | |
405 | /// The parts of the display that are partially obscured by system UI, |
406 | /// typically by the hardware display "notches" or the system status bar. |
407 | /// |
408 | /// If you consumed this padding (e.g. by building a widget that envelops or |
409 | /// accounts for this padding in its layout in such a way that children are |
410 | /// no longer exposed to this padding), you should remove this padding |
411 | /// for subsequent descendants in the widget tree by inserting a new |
412 | /// [MediaQuery] widget using the [MediaQuery.removePadding] factory. |
413 | /// |
414 | /// Padding is derived from the values of [viewInsets] and [viewPadding]. |
415 | /// |
416 | /// {@youtube 560 315 https://www.youtube.com/watch?v=ceCo8U0XHqw} |
417 | /// |
418 | /// See also: |
419 | /// |
420 | /// * [FlutterView], which provides some additional detail about this |
421 | /// property and how it relates to [viewInsets] and [viewPadding]. |
422 | /// * [SafeArea], a widget that consumes this padding with a [Padding] widget |
423 | /// and automatically removes it from the [MediaQuery] for its child. |
424 | final EdgeInsets padding; |
425 | |
426 | /// The parts of the display that are partially obscured by system UI, |
427 | /// typically by the hardware display "notches" or the system status bar. |
428 | /// |
429 | /// This value remains the same regardless of whether the system is reporting |
430 | /// other obstructions in the same physical area of the screen. For example, a |
431 | /// software keyboard on the bottom of the screen that may cover and consume |
432 | /// the same area that requires bottom padding will not affect this value. |
433 | /// |
434 | /// This value is independent of the [padding] and [viewInsets]: their values |
435 | /// are measured from the edges of the [MediaQuery] widget's bounds. The |
436 | /// bounds of the top level MediaQuery created by [WidgetsApp] are the |
437 | /// same as the window that contains the app. On mobile devices, this will |
438 | /// typically be the full screen. |
439 | /// |
440 | /// {@youtube 560 315 https://www.youtube.com/watch?v=ceCo8U0XHqw} |
441 | /// |
442 | /// See also: |
443 | /// |
444 | /// * [FlutterView], which provides some additional detail about this |
445 | /// property and how it relates to [padding] and [viewInsets]. |
446 | final EdgeInsets viewPadding; |
447 | |
448 | /// The areas along the edges of the display where the system consumes |
449 | /// certain input events and blocks delivery of those events to the app. |
450 | /// |
451 | /// Starting with Android Q, simple swipe gestures that start within the |
452 | /// [systemGestureInsets] areas are used by the system for page navigation |
453 | /// and may not be delivered to the app. Taps and swipe gestures that begin |
454 | /// with a long-press are delivered to the app, but simple press-drag-release |
455 | /// swipe gestures which begin within the area defined by [systemGestureInsets] |
456 | /// may not be. |
457 | /// |
458 | /// Apps should avoid locating gesture detectors within the system gesture |
459 | /// insets area. Apps should feel free to put visual elements within |
460 | /// this area. |
461 | /// |
462 | /// This property is currently only expected to be set to a non-default value |
463 | /// on Android starting with version Q. |
464 | /// |
465 | /// {@tool dartpad} |
466 | /// For apps that might be deployed on Android Q devices with full gesture |
467 | /// navigation enabled, use [systemGestureInsets] with [Padding] |
468 | /// to avoid having the left and right edges of the [Slider] from appearing |
469 | /// within the area reserved for system gesture navigation. |
470 | /// |
471 | /// By default, [Slider]s expand to fill the available width. So, we pad the |
472 | /// left and right sides. |
473 | /// |
474 | /// ** See code in examples/api/lib/widgets/media_query/media_query_data.system_gesture_insets.0.dart ** |
475 | /// {@end-tool} |
476 | final EdgeInsets systemGestureInsets; |
477 | |
478 | /// Whether to use 24-hour format when formatting time. |
479 | /// |
480 | /// The behavior of this flag is different across platforms: |
481 | /// |
482 | /// - On Android this flag is reported directly from the user settings called |
483 | /// "Use 24-hour format". It applies to any locale used by the application, |
484 | /// whether it is the system-wide locale, or the custom locale set by the |
485 | /// application. |
486 | /// - On iOS this flag is set to true when the user setting called "24-Hour |
487 | /// Time" is set or the system-wide locale's default uses 24-hour |
488 | /// formatting. |
489 | final bool alwaysUse24HourFormat; |
490 | |
491 | /// Whether the user is using an accessibility service like TalkBack or |
492 | /// VoiceOver to interact with the application. |
493 | /// |
494 | /// When this setting is true, features such as timeouts should be disabled or |
495 | /// have minimum durations increased. |
496 | /// |
497 | /// See also: |
498 | /// |
499 | /// * [dart:ui.PlatformDispatcher.accessibilityFeatures], where the setting originates. |
500 | final bool accessibleNavigation; |
501 | |
502 | /// Whether the device is inverting the colors of the platform. |
503 | /// |
504 | /// This flag is currently only updated on iOS devices. |
505 | /// |
506 | /// See also: |
507 | /// |
508 | /// * [dart:ui.PlatformDispatcher.accessibilityFeatures], where the setting |
509 | /// originates. |
510 | final bool invertColors; |
511 | |
512 | /// Whether the user requested a high contrast between foreground and background |
513 | /// content on iOS, via Settings -> Accessibility -> Increase Contrast. |
514 | /// |
515 | /// This flag is currently only updated on iOS devices that are running iOS 13 |
516 | /// or above. |
517 | final bool highContrast; |
518 | |
519 | /// Whether the user requested to show on/off labels inside switches on iOS, |
520 | /// via Settings -> Accessibility -> Display & Text Size -> On/Off Labels. |
521 | /// |
522 | /// See also: |
523 | /// |
524 | /// * [dart:ui.PlatformDispatcher.accessibilityFeatures], where the setting |
525 | /// originates. |
526 | final bool onOffSwitchLabels; |
527 | |
528 | /// Whether the platform is requesting that animations be disabled or reduced |
529 | /// as much as possible. |
530 | /// |
531 | /// See also: |
532 | /// |
533 | /// * [dart:ui.PlatformDispatcher.accessibilityFeatures], where the setting |
534 | /// originates. |
535 | final bool disableAnimations; |
536 | |
537 | /// Whether the platform is requesting that text be drawn with a bold font |
538 | /// weight. |
539 | /// |
540 | /// See also: |
541 | /// |
542 | /// * [dart:ui.PlatformDispatcher.accessibilityFeatures], where the setting |
543 | /// originates. |
544 | final bool boldText; |
545 | |
546 | /// Describes the navigation mode requested by the platform. |
547 | /// |
548 | /// Some user interfaces are better navigated using a directional pad (DPAD) |
549 | /// or arrow keys, and for those interfaces, some widgets need to handle these |
550 | /// directional events differently. In order to know when to do that, these |
551 | /// widgets will look for the navigation mode in effect for their context. |
552 | /// |
553 | /// For instance, in a television interface, [NavigationMode.directional] |
554 | /// should be set, so that directional navigation is used to navigate away |
555 | /// from a text field using the DPAD. In contrast, on a regular desktop |
556 | /// application with the [navigationMode] set to [NavigationMode.traditional], |
557 | /// the arrow keys are used to move the cursor instead of navigating away. |
558 | /// |
559 | /// The [NavigationMode] values indicate the type of navigation to be used in |
560 | /// a widget subtree for those widgets sensitive to it. |
561 | final NavigationMode navigationMode; |
562 | |
563 | /// The gesture settings for the view this media query is derived from. |
564 | /// |
565 | /// This contains platform specific configuration for gesture behavior, |
566 | /// such as touch slop. These settings should be favored for configuring |
567 | /// gesture behavior over the framework constants. |
568 | final DeviceGestureSettings gestureSettings; |
569 | |
570 | /// {@macro dart.ui.ViewConfiguration.displayFeatures} |
571 | /// |
572 | /// See also: |
573 | /// |
574 | /// * [dart:ui.DisplayFeatureType], which lists the different types of |
575 | /// display features and explains the differences between them. |
576 | /// * [dart:ui.DisplayFeatureState], which lists the possible states for |
577 | /// folding features ([dart:ui.DisplayFeatureType.fold] and |
578 | /// [dart:ui.DisplayFeatureType.hinge]). |
579 | final List<ui.DisplayFeature> displayFeatures; |
580 | |
581 | /// Whether showing the system context menu is supported. |
582 | /// |
583 | /// For example, on iOS 16.0 and above, the system text selection context menu |
584 | /// may be shown instead of the Flutter-drawn context menu in order to avoid |
585 | /// the iOS clipboard access notification when the "Paste" button is pressed. |
586 | /// |
587 | /// See also: |
588 | /// |
589 | /// * [SystemContextMenuController] and [SystemContextMenu], which may be |
590 | /// used to show the system context menu when this flag indicates it's |
591 | /// supported. |
592 | final bool supportsShowingSystemContextMenu; |
593 | |
594 | /// The orientation of the media (e.g., whether the device is in landscape or |
595 | /// portrait mode). |
596 | Orientation get orientation { |
597 | return size.width > size.height ? Orientation.landscape : Orientation.portrait; |
598 | } |
599 | |
600 | /// Creates a copy of this media query data but with the given fields replaced |
601 | /// with the new values. |
602 | /// |
603 | /// The `textScaler` parameter and `textScaleFactor` parameter must not be |
604 | /// both specified. |
605 | MediaQueryData copyWith({ |
606 | Size? size, |
607 | double? devicePixelRatio, |
608 | @Deprecated( |
609 | 'Use textScaler instead. ' |
610 | 'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. ' |
611 | 'This feature was deprecated after v3.12.0-2.0.pre.' , |
612 | ) |
613 | double? textScaleFactor, |
614 | TextScaler? textScaler, |
615 | Brightness? platformBrightness, |
616 | EdgeInsets? padding, |
617 | EdgeInsets? viewPadding, |
618 | EdgeInsets? viewInsets, |
619 | EdgeInsets? systemGestureInsets, |
620 | bool? alwaysUse24HourFormat, |
621 | bool? highContrast, |
622 | bool? onOffSwitchLabels, |
623 | bool? disableAnimations, |
624 | bool? invertColors, |
625 | bool? accessibleNavigation, |
626 | bool? boldText, |
627 | NavigationMode? navigationMode, |
628 | DeviceGestureSettings? gestureSettings, |
629 | List<ui.DisplayFeature>? displayFeatures, |
630 | bool? supportsShowingSystemContextMenu, |
631 | }) { |
632 | assert(textScaleFactor == null || textScaler == null); |
633 | if (textScaleFactor != null) { |
634 | textScaler ??= TextScaler.linear(textScaleFactor); |
635 | } |
636 | return MediaQueryData( |
637 | size: size ?? this.size, |
638 | devicePixelRatio: devicePixelRatio ?? this.devicePixelRatio, |
639 | textScaler: textScaler ?? this.textScaler, |
640 | platformBrightness: platformBrightness ?? this.platformBrightness, |
641 | padding: padding ?? this.padding, |
642 | viewPadding: viewPadding ?? this.viewPadding, |
643 | viewInsets: viewInsets ?? this.viewInsets, |
644 | systemGestureInsets: systemGestureInsets ?? this.systemGestureInsets, |
645 | alwaysUse24HourFormat: alwaysUse24HourFormat ?? this.alwaysUse24HourFormat, |
646 | invertColors: invertColors ?? this.invertColors, |
647 | highContrast: highContrast ?? this.highContrast, |
648 | onOffSwitchLabels: onOffSwitchLabels ?? this.onOffSwitchLabels, |
649 | disableAnimations: disableAnimations ?? this.disableAnimations, |
650 | accessibleNavigation: accessibleNavigation ?? this.accessibleNavigation, |
651 | boldText: boldText ?? this.boldText, |
652 | navigationMode: navigationMode ?? this.navigationMode, |
653 | gestureSettings: gestureSettings ?? this.gestureSettings, |
654 | displayFeatures: displayFeatures ?? this.displayFeatures, |
655 | supportsShowingSystemContextMenu: supportsShowingSystemContextMenu ?? this.supportsShowingSystemContextMenu, |
656 | ); |
657 | } |
658 | |
659 | /// Creates a copy of this media query data but with the given [padding]s |
660 | /// replaced with zero. |
661 | /// |
662 | /// If all four of the `removeLeft`, `removeTop`, `removeRight`, and |
663 | /// `removeBottom` arguments are false (the default), then this |
664 | /// [MediaQueryData] is returned unmodified. |
665 | /// |
666 | /// See also: |
667 | /// |
668 | /// * [MediaQuery.removePadding], which uses this method to remove [padding] |
669 | /// from the ambient [MediaQuery]. |
670 | /// * [SafeArea], which both removes the padding from the [MediaQuery] and |
671 | /// adds a [Padding] widget. |
672 | /// * [removeViewInsets], the same thing but for [viewInsets]. |
673 | /// * [removeViewPadding], the same thing but for [viewPadding]. |
674 | MediaQueryData removePadding({ |
675 | bool removeLeft = false, |
676 | bool removeTop = false, |
677 | bool removeRight = false, |
678 | bool removeBottom = false, |
679 | }) { |
680 | if (!(removeLeft || removeTop || removeRight || removeBottom)) { |
681 | return this; |
682 | } |
683 | return copyWith( |
684 | padding: padding.copyWith( |
685 | left: removeLeft ? 0.0 : null, |
686 | top: removeTop ? 0.0 : null, |
687 | right: removeRight ? 0.0 : null, |
688 | bottom: removeBottom ? 0.0 : null, |
689 | ), |
690 | viewPadding: viewPadding.copyWith( |
691 | left: removeLeft ? math.max(0.0, viewPadding.left - padding.left) : null, |
692 | top: removeTop ? math.max(0.0, viewPadding.top - padding.top) : null, |
693 | right: removeRight ? math.max(0.0, viewPadding.right - padding.right) : null, |
694 | bottom: removeBottom ? math.max(0.0, viewPadding.bottom - padding.bottom) : null, |
695 | ), |
696 | ); |
697 | } |
698 | |
699 | /// Creates a copy of this media query data but with the given [viewInsets] |
700 | /// replaced with zero. |
701 | /// |
702 | /// If all four of the `removeLeft`, `removeTop`, `removeRight`, and |
703 | /// `removeBottom` arguments are false (the default), then this |
704 | /// [MediaQueryData] is returned unmodified. |
705 | /// |
706 | /// See also: |
707 | /// |
708 | /// * [MediaQuery.removeViewInsets], which uses this method to remove |
709 | /// [viewInsets] from the ambient [MediaQuery]. |
710 | /// * [removePadding], the same thing but for [padding]. |
711 | /// * [removeViewPadding], the same thing but for [viewPadding]. |
712 | MediaQueryData removeViewInsets({ |
713 | bool removeLeft = false, |
714 | bool removeTop = false, |
715 | bool removeRight = false, |
716 | bool removeBottom = false, |
717 | }) { |
718 | if (!(removeLeft || removeTop || removeRight || removeBottom)) { |
719 | return this; |
720 | } |
721 | return copyWith( |
722 | viewPadding: viewPadding.copyWith( |
723 | left: removeLeft ? math.max(0.0, viewPadding.left - viewInsets.left) : null, |
724 | top: removeTop ? math.max(0.0, viewPadding.top - viewInsets.top) : null, |
725 | right: removeRight ? math.max(0.0, viewPadding.right - viewInsets.right) : null, |
726 | bottom: removeBottom ? math.max(0.0, viewPadding.bottom - viewInsets.bottom) : null, |
727 | ), |
728 | viewInsets: viewInsets.copyWith( |
729 | left: removeLeft ? 0.0 : null, |
730 | top: removeTop ? 0.0 : null, |
731 | right: removeRight ? 0.0 : null, |
732 | bottom: removeBottom ? 0.0 : null, |
733 | ), |
734 | ); |
735 | } |
736 | |
737 | /// Creates a copy of this media query data but with the given [viewPadding] |
738 | /// replaced with zero. |
739 | /// |
740 | /// If all four of the `removeLeft`, `removeTop`, `removeRight`, and |
741 | /// `removeBottom` arguments are false (the default), then this |
742 | /// [MediaQueryData] is returned unmodified. |
743 | /// |
744 | /// See also: |
745 | /// |
746 | /// * [MediaQuery.removeViewPadding], which uses this method to remove |
747 | /// [viewPadding] from the ambient [MediaQuery]. |
748 | /// * [removePadding], the same thing but for [padding]. |
749 | /// * [removeViewInsets], the same thing but for [viewInsets]. |
750 | MediaQueryData removeViewPadding({ |
751 | bool removeLeft = false, |
752 | bool removeTop = false, |
753 | bool removeRight = false, |
754 | bool removeBottom = false, |
755 | }) { |
756 | if (!(removeLeft || removeTop || removeRight || removeBottom)) { |
757 | return this; |
758 | } |
759 | return copyWith( |
760 | padding: padding.copyWith( |
761 | left: removeLeft ? 0.0 : null, |
762 | top: removeTop ? 0.0 : null, |
763 | right: removeRight ? 0.0 : null, |
764 | bottom: removeBottom ? 0.0 : null, |
765 | ), |
766 | viewPadding: viewPadding.copyWith( |
767 | left: removeLeft ? 0.0 : null, |
768 | top: removeTop ? 0.0 : null, |
769 | right: removeRight ? 0.0 : null, |
770 | bottom: removeBottom ? 0.0 : null, |
771 | ), |
772 | ); |
773 | } |
774 | |
775 | /// Creates a copy of this media query data by removing [displayFeatures] that |
776 | /// are completely outside the given sub-screen and adjusting the [padding], |
777 | /// [viewInsets] and [viewPadding] to be zero on the sides that are not |
778 | /// included in the sub-screen. |
779 | /// |
780 | /// Returns unmodified [MediaQueryData] if the sub-screen coincides with the |
781 | /// available screen space. |
782 | /// |
783 | /// Asserts in debug mode, if the given sub-screen is outside the available |
784 | /// screen space. |
785 | /// |
786 | /// See also: |
787 | /// |
788 | /// * [DisplayFeatureSubScreen], which removes the display features that |
789 | /// split the screen, from the [MediaQuery] and adds a [Padding] widget to |
790 | /// position the child to match the selected sub-screen. |
791 | MediaQueryData removeDisplayFeatures(Rect subScreen) { |
792 | assert(subScreen.left >= 0.0 && subScreen.top >= 0.0 && |
793 | subScreen.right <= size.width && subScreen.bottom <= size.height, |
794 | "'subScreen' argument cannot be outside the bounds of the screen" ); |
795 | if (subScreen.size == size && subScreen.topLeft == Offset.zero) { |
796 | return this; |
797 | } |
798 | final double rightInset = size.width - subScreen.right; |
799 | final double bottomInset = size.height - subScreen.bottom; |
800 | return copyWith( |
801 | padding: EdgeInsets.only( |
802 | left: math.max(0.0, padding.left - subScreen.left), |
803 | top: math.max(0.0, padding.top - subScreen.top), |
804 | right: math.max(0.0, padding.right - rightInset), |
805 | bottom: math.max(0.0, padding.bottom - bottomInset), |
806 | ), |
807 | viewPadding: EdgeInsets.only( |
808 | left: math.max(0.0, viewPadding.left - subScreen.left), |
809 | top: math.max(0.0, viewPadding.top - subScreen.top), |
810 | right: math.max(0.0, viewPadding.right - rightInset), |
811 | bottom: math.max(0.0, viewPadding.bottom - bottomInset), |
812 | ), |
813 | viewInsets: EdgeInsets.only( |
814 | left: math.max(0.0, viewInsets.left - subScreen.left), |
815 | top: math.max(0.0, viewInsets.top - subScreen.top), |
816 | right: math.max(0.0, viewInsets.right - rightInset), |
817 | bottom: math.max(0.0, viewInsets.bottom - bottomInset), |
818 | ), |
819 | displayFeatures: displayFeatures.where( |
820 | (ui.DisplayFeature displayFeature) => subScreen.overlaps(displayFeature.bounds) |
821 | ).toList(), |
822 | ); |
823 | } |
824 | |
825 | @override |
826 | bool operator ==(Object other) { |
827 | if (other.runtimeType != runtimeType) { |
828 | return false; |
829 | } |
830 | return other is MediaQueryData |
831 | && other.size == size |
832 | && other.devicePixelRatio == devicePixelRatio |
833 | && other.textScaleFactor == textScaleFactor |
834 | && other.platformBrightness == platformBrightness |
835 | && other.padding == padding |
836 | && other.viewPadding == viewPadding |
837 | && other.viewInsets == viewInsets |
838 | && other.systemGestureInsets == systemGestureInsets |
839 | && other.alwaysUse24HourFormat == alwaysUse24HourFormat |
840 | && other.highContrast == highContrast |
841 | && other.onOffSwitchLabels == onOffSwitchLabels |
842 | && other.disableAnimations == disableAnimations |
843 | && other.invertColors == invertColors |
844 | && other.accessibleNavigation == accessibleNavigation |
845 | && other.boldText == boldText |
846 | && other.navigationMode == navigationMode |
847 | && other.gestureSettings == gestureSettings |
848 | && listEquals(other.displayFeatures, displayFeatures) |
849 | && other.supportsShowingSystemContextMenu == supportsShowingSystemContextMenu; |
850 | } |
851 | |
852 | @override |
853 | int get hashCode => Object.hash( |
854 | size, |
855 | devicePixelRatio, |
856 | textScaleFactor, |
857 | platformBrightness, |
858 | padding, |
859 | viewPadding, |
860 | viewInsets, |
861 | alwaysUse24HourFormat, |
862 | highContrast, |
863 | onOffSwitchLabels, |
864 | disableAnimations, |
865 | invertColors, |
866 | accessibleNavigation, |
867 | boldText, |
868 | navigationMode, |
869 | gestureSettings, |
870 | Object.hashAll(displayFeatures), |
871 | supportsShowingSystemContextMenu, |
872 | ); |
873 | |
874 | @override |
875 | String toString() { |
876 | final List<String> properties = <String>[ |
877 | 'size: $size' , |
878 | 'devicePixelRatio: ${devicePixelRatio.toStringAsFixed(1)}' , |
879 | 'textScaler: $textScaler' , |
880 | 'platformBrightness: $platformBrightness' , |
881 | 'padding: $padding' , |
882 | 'viewPadding: $viewPadding' , |
883 | 'viewInsets: $viewInsets' , |
884 | 'systemGestureInsets: $systemGestureInsets' , |
885 | 'alwaysUse24HourFormat: $alwaysUse24HourFormat' , |
886 | 'accessibleNavigation: $accessibleNavigation' , |
887 | 'highContrast: $highContrast' , |
888 | 'onOffSwitchLabels: $onOffSwitchLabels' , |
889 | 'disableAnimations: $disableAnimations' , |
890 | 'invertColors: $invertColors' , |
891 | 'boldText: $boldText' , |
892 | 'navigationMode: ${navigationMode.name}' , |
893 | 'gestureSettings: $gestureSettings' , |
894 | 'displayFeatures: $displayFeatures' , |
895 | 'supportsShowingSystemContextMenu: $supportsShowingSystemContextMenu' , |
896 | ]; |
897 | return ' ${objectRuntimeType(this, 'MediaQueryData' )}( ${properties.join(', ' )})' ; |
898 | } |
899 | } |
900 | |
901 | /// Establishes a subtree in which media queries resolve to the given data. |
902 | /// |
903 | /// For example, to learn the size of the current view (e.g., |
904 | /// the [FlutterView] containing your app), you can use [MediaQuery.sizeOf]: |
905 | /// `MediaQuery.sizeOf(context)`. |
906 | /// |
907 | /// Querying the current media using specific methods (for example, |
908 | /// [MediaQuery.sizeOf] or [MediaQuery.paddingOf]) will cause your widget to |
909 | /// rebuild automatically whenever that specific property changes. |
910 | /// |
911 | /// {@template flutter.widgets.media_query.MediaQuery.useSpecific} |
912 | /// Querying using [MediaQuery.of] will cause your widget to rebuild |
913 | /// automatically whenever _any_ field of the [MediaQueryData] changes (e.g., if |
914 | /// the user rotates their device). Therefore, unless you are concerned with the |
915 | /// entire [MediaQueryData] object changing, prefer using the specific methods |
916 | /// (for example: [MediaQuery.sizeOf] and [MediaQuery.paddingOf]), as it will |
917 | /// rebuild more efficiently. |
918 | /// |
919 | /// If no [MediaQuery] is in scope then [MediaQuery.of] and the "...Of" methods |
920 | /// similar to [MediaQuery.sizeOf] will throw an exception. Alternatively, the |
921 | /// "maybe-" variant methods (such as [MediaQuery.maybeOf] and |
922 | /// [MediaQuery.maybeSizeOf]) can be used, which return null, instead of |
923 | /// throwing, when no [MediaQuery] is in scope. |
924 | /// {@endtemplate} |
925 | /// |
926 | /// {@youtube 560 315 https://www.youtube.com/watch?v=A3WrA4zAaPw} |
927 | /// |
928 | /// See also: |
929 | /// |
930 | /// * [WidgetsApp] and [MaterialApp], which introduce a [MediaQuery] and keep |
931 | /// it up to date with the current screen metrics as they change. |
932 | /// * [MediaQueryData], the data structure that represents the metrics. |
933 | class MediaQuery extends InheritedModel<_MediaQueryAspect> { |
934 | /// Creates a widget that provides [MediaQueryData] to its descendants. |
935 | const MediaQuery({ |
936 | super.key, |
937 | required this.data, |
938 | required super.child, |
939 | }); |
940 | |
941 | /// Creates a new [MediaQuery] that inherits from the ambient [MediaQuery] |
942 | /// from the given context, but removes the specified padding. |
943 | /// |
944 | /// This should be inserted into the widget tree when the [MediaQuery] padding |
945 | /// is consumed by a widget in such a way that the padding is no longer |
946 | /// exposed to the widget's descendants or siblings. |
947 | /// |
948 | /// The [context] argument must have a [MediaQuery] in scope. |
949 | /// |
950 | /// If all four of the `removeLeft`, `removeTop`, `removeRight`, and |
951 | /// `removeBottom` arguments are false (the default), then the returned |
952 | /// [MediaQuery] reuses the ambient [MediaQueryData] unmodified, which is not |
953 | /// particularly useful. |
954 | /// |
955 | /// See also: |
956 | /// |
957 | /// * [SafeArea], which both removes the padding from the [MediaQuery] and |
958 | /// adds a [Padding] widget. |
959 | /// * [MediaQueryData.padding], the affected property of the |
960 | /// [MediaQueryData]. |
961 | /// * [MediaQuery.removeViewInsets], the same thing but for [MediaQueryData.viewInsets]. |
962 | /// * [MediaQuery.removeViewPadding], the same thing but for |
963 | /// [MediaQueryData.viewPadding]. |
964 | MediaQuery.removePadding({ |
965 | super.key, |
966 | required BuildContext context, |
967 | bool removeLeft = false, |
968 | bool removeTop = false, |
969 | bool removeRight = false, |
970 | bool removeBottom = false, |
971 | required super.child, |
972 | }) : data = MediaQuery.of(context).removePadding( |
973 | removeLeft: removeLeft, |
974 | removeTop: removeTop, |
975 | removeRight: removeRight, |
976 | removeBottom: removeBottom, |
977 | ); |
978 | |
979 | /// Creates a new [MediaQuery] that inherits from the ambient [MediaQuery] |
980 | /// from the given context, but removes the specified view insets. |
981 | /// |
982 | /// This should be inserted into the widget tree when the [MediaQuery] view |
983 | /// insets are consumed by a widget in such a way that the view insets are no |
984 | /// longer exposed to the widget's descendants or siblings. |
985 | /// |
986 | /// The [context] argument must have a [MediaQuery] in scope. |
987 | /// |
988 | /// If all four of the `removeLeft`, `removeTop`, `removeRight`, and |
989 | /// `removeBottom` arguments are false (the default), then the returned |
990 | /// [MediaQuery] reuses the ambient [MediaQueryData] unmodified, which is not |
991 | /// particularly useful. |
992 | /// |
993 | /// See also: |
994 | /// |
995 | /// * [MediaQueryData.viewInsets], the affected property of the |
996 | /// [MediaQueryData]. |
997 | /// * [MediaQuery.removePadding], the same thing but for [MediaQueryData.padding]. |
998 | /// * [MediaQuery.removeViewPadding], the same thing but for |
999 | /// [MediaQueryData.viewPadding]. |
1000 | MediaQuery.removeViewInsets({ |
1001 | super.key, |
1002 | required BuildContext context, |
1003 | bool removeLeft = false, |
1004 | bool removeTop = false, |
1005 | bool removeRight = false, |
1006 | bool removeBottom = false, |
1007 | required super.child, |
1008 | }) : data = MediaQuery.of(context).removeViewInsets( |
1009 | removeLeft: removeLeft, |
1010 | removeTop: removeTop, |
1011 | removeRight: removeRight, |
1012 | removeBottom: removeBottom, |
1013 | ); |
1014 | |
1015 | /// Creates a new [MediaQuery] that inherits from the ambient [MediaQuery] |
1016 | /// from the given context, but removes the specified view padding. |
1017 | /// |
1018 | /// This should be inserted into the widget tree when the [MediaQuery] view |
1019 | /// padding is consumed by a widget in such a way that the view padding is no |
1020 | /// longer exposed to the widget's descendants or siblings. |
1021 | /// |
1022 | /// The [context] argument must have a [MediaQuery] in scope. |
1023 | /// |
1024 | /// If all four of the `removeLeft`, `removeTop`, `removeRight`, and |
1025 | /// `removeBottom` arguments are false (the default), then the returned |
1026 | /// [MediaQuery] reuses the ambient [MediaQueryData] unmodified, which is not |
1027 | /// particularly useful. |
1028 | /// |
1029 | /// See also: |
1030 | /// |
1031 | /// * [MediaQueryData.viewPadding], the affected property of the |
1032 | /// [MediaQueryData]. |
1033 | /// * [MediaQuery.removePadding], the same thing but for [MediaQueryData.padding]. |
1034 | /// * [MediaQuery.removeViewInsets], the same thing but for [MediaQueryData.viewInsets]. |
1035 | MediaQuery.removeViewPadding({ |
1036 | super.key, |
1037 | required BuildContext context, |
1038 | bool removeLeft = false, |
1039 | bool removeTop = false, |
1040 | bool removeRight = false, |
1041 | bool removeBottom = false, |
1042 | required super.child, |
1043 | }) : data = MediaQuery.of(context).removeViewPadding( |
1044 | removeLeft: removeLeft, |
1045 | removeTop: removeTop, |
1046 | removeRight: removeRight, |
1047 | removeBottom: removeBottom, |
1048 | ); |
1049 | |
1050 | /// Deprecated. Use [MediaQuery.fromView] instead. |
1051 | /// |
1052 | /// This constructor was operating on a single window assumption. In |
1053 | /// preparation for Flutter's upcoming multi-window support, it has been |
1054 | /// deprecated. |
1055 | /// |
1056 | /// Replaced by [MediaQuery.fromView], which requires specifying the |
1057 | /// [FlutterView] the [MediaQuery] is constructed for. The [FlutterView] can, |
1058 | /// for example, be obtained from the context via [View.of] or from |
1059 | /// [PlatformDispatcher.views]. |
1060 | @Deprecated( |
1061 | 'Use MediaQuery.fromView instead. ' |
1062 | 'This constructor was deprecated in preparation for the upcoming multi-window support. ' |
1063 | 'This feature was deprecated after v3.7.0-32.0.pre.' |
1064 | ) |
1065 | static Widget fromWindow({ |
1066 | Key? key, |
1067 | required Widget child, |
1068 | }) { |
1069 | return _MediaQueryFromView( |
1070 | key: key, |
1071 | view: WidgetsBinding.instance.window, |
1072 | ignoreParentData: true, |
1073 | child: child, |
1074 | ); |
1075 | } |
1076 | |
1077 | /// Wraps the [child] in a [MediaQuery] which is built using data from the |
1078 | /// provided [view]. |
1079 | /// |
1080 | /// The [MediaQuery] is constructed using the platform-specific data of the |
1081 | /// surrounding [MediaQuery] and the view-specific data of the provided |
1082 | /// [view]. If no surrounding [MediaQuery] exists, the platform-specific data |
1083 | /// is generated from the [PlatformDispatcher] associated with the provided |
1084 | /// [view]. Any information that's exposed via the [PlatformDispatcher] is |
1085 | /// considered platform-specific. Data exposed directly on the [FlutterView] |
1086 | /// (excluding its [FlutterView.platformDispatcher] property) is considered |
1087 | /// view-specific. |
1088 | /// |
1089 | /// The injected [MediaQuery] automatically updates when any of the data used |
1090 | /// to construct it changes. |
1091 | static Widget fromView({ |
1092 | Key? key, |
1093 | required FlutterView view, |
1094 | required Widget child, |
1095 | }) { |
1096 | return _MediaQueryFromView( |
1097 | key: key, |
1098 | view: view, |
1099 | child: child, |
1100 | ); |
1101 | } |
1102 | |
1103 | /// Wraps the `child` in a [MediaQuery] with its [MediaQueryData.textScaler] |
1104 | /// set to [TextScaler.noScaling]. |
1105 | /// |
1106 | /// The returned widget must be inserted in a widget tree below an existing |
1107 | /// [MediaQuery] widget. |
1108 | /// |
1109 | /// This can be used to prevent, for example, icon fonts from scaling as the |
1110 | /// user adjusts the platform's text scaling value. |
1111 | static Widget withNoTextScaling({ |
1112 | Key? key, |
1113 | required Widget child, |
1114 | }) { |
1115 | return Builder( |
1116 | key: key, |
1117 | builder: (BuildContext context) { |
1118 | assert(debugCheckHasMediaQuery(context)); |
1119 | return MediaQuery( |
1120 | data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling), |
1121 | child: child, |
1122 | ); |
1123 | }, |
1124 | ); |
1125 | } |
1126 | |
1127 | /// Wraps the `child` in a [MediaQuery] and applies [TextScaler.clamp] on the |
1128 | /// current [MediaQueryData.textScaler]. |
1129 | /// |
1130 | /// The returned widget must be inserted in a widget tree below an existing |
1131 | /// [MediaQuery] widget. |
1132 | /// |
1133 | /// This is a convenience function to restrict the range of the scaled text |
1134 | /// size to `[minScaleFactor * fontSize, maxScaleFactor * fontSize]` (to |
1135 | /// prevent excessive text scaling that would break the UI, for example). When |
1136 | /// `minScaleFactor` equals `maxScaleFactor`, the scaler becomes |
1137 | /// `TextScaler.linear(minScaleFactor)`. |
1138 | static Widget withClampedTextScaling({ |
1139 | Key? key, |
1140 | double minScaleFactor = 0.0, |
1141 | double maxScaleFactor = double.infinity, |
1142 | required Widget child, |
1143 | }) { |
1144 | assert(maxScaleFactor >= minScaleFactor); |
1145 | assert(!maxScaleFactor.isNaN); |
1146 | assert(minScaleFactor.isFinite); |
1147 | assert(minScaleFactor >= 0); |
1148 | |
1149 | return Builder(builder: (BuildContext context) { |
1150 | assert(debugCheckHasMediaQuery(context)); |
1151 | final MediaQueryData data = MediaQuery.of(context); |
1152 | return MediaQuery( |
1153 | data: data.copyWith( |
1154 | textScaler: data.textScaler.clamp(minScaleFactor: minScaleFactor, maxScaleFactor: maxScaleFactor), |
1155 | ), |
1156 | child: child, |
1157 | ); |
1158 | }); |
1159 | } |
1160 | |
1161 | /// Contains information about the current media. |
1162 | /// |
1163 | /// For example, the [MediaQueryData.size] property contains the width and |
1164 | /// height of the current window. |
1165 | final MediaQueryData data; |
1166 | |
1167 | /// The data from the closest instance of this class that encloses the given |
1168 | /// context. |
1169 | /// |
1170 | /// You can use this function to query the entire set of data held in the |
1171 | /// current [MediaQueryData] object. When any of that information changes, |
1172 | /// your widget will be scheduled to be rebuilt, keeping your widget |
1173 | /// up-to-date. |
1174 | /// |
1175 | /// Since it is typical that the widget only requires a subset of properties |
1176 | /// of the [MediaQueryData] object, prefer using the more specific methods |
1177 | /// (for example: [MediaQuery.sizeOf] and [MediaQuery.paddingOf]), as those |
1178 | /// methods will not cause a widget to rebuild when unrelated properties are |
1179 | /// updated. |
1180 | /// |
1181 | /// Typical usage is as follows: |
1182 | /// |
1183 | /// ```dart |
1184 | /// MediaQueryData media = MediaQuery.of(context); |
1185 | /// ``` |
1186 | /// |
1187 | /// If there is no [MediaQuery] in scope, this method will throw a [TypeError] |
1188 | /// exception in release builds, and throw a descriptive [FlutterError] in |
1189 | /// debug builds. |
1190 | /// |
1191 | /// See also: |
1192 | /// |
1193 | /// * [maybeOf], which doesn't throw or assert if it doesn't find a |
1194 | /// [MediaQuery] ancestor. It returns null instead. |
1195 | /// * [sizeOf] and other specific methods for retrieving and depending on |
1196 | /// changes of a specific value. |
1197 | static MediaQueryData of(BuildContext context) { |
1198 | return _of(context); |
1199 | } |
1200 | |
1201 | static MediaQueryData _of(BuildContext context, [_MediaQueryAspect? aspect]) { |
1202 | assert(debugCheckHasMediaQuery(context)); |
1203 | return InheritedModel.inheritFrom<MediaQuery>(context, aspect: aspect)!.data; |
1204 | } |
1205 | |
1206 | /// The data from the closest instance of this class that encloses the given |
1207 | /// context, if any. |
1208 | /// |
1209 | /// Use this function if you want to allow situations where no [MediaQuery] is |
1210 | /// in scope. Prefer using [MediaQuery.of] in situations where a media query |
1211 | /// is always expected to exist. |
1212 | /// |
1213 | /// If there is no [MediaQuery] in scope, then this function will return null. |
1214 | /// |
1215 | /// You can use this function to query the entire set of data held in the |
1216 | /// current [MediaQueryData] object. When any of that information changes, |
1217 | /// your widget will be scheduled to be rebuilt, keeping your widget |
1218 | /// up-to-date. |
1219 | /// |
1220 | /// Since it is typical that the widget only requires a subset of properties |
1221 | /// of the [MediaQueryData] object, prefer using the more specific methods |
1222 | /// (for example: [MediaQuery.maybeSizeOf] and [MediaQuery.maybePaddingOf]), |
1223 | /// as those methods will not cause a widget to rebuild when unrelated |
1224 | /// properties are updated. |
1225 | /// |
1226 | /// Typical usage is as follows: |
1227 | /// |
1228 | /// ```dart |
1229 | /// MediaQueryData? mediaQuery = MediaQuery.maybeOf(context); |
1230 | /// if (mediaQuery == null) { |
1231 | /// // Do something else instead. |
1232 | /// } |
1233 | /// ``` |
1234 | /// |
1235 | /// See also: |
1236 | /// |
1237 | /// * [of], which will throw if it doesn't find a [MediaQuery] ancestor, |
1238 | /// instead of returning null. |
1239 | /// * [maybeSizeOf] and other specific methods for retrieving and depending on |
1240 | /// changes of a specific value. |
1241 | static MediaQueryData? maybeOf(BuildContext context) { |
1242 | return _maybeOf(context); |
1243 | } |
1244 | |
1245 | static MediaQueryData? _maybeOf(BuildContext context, [_MediaQueryAspect? aspect]) { |
1246 | return InheritedModel.inheritFrom<MediaQuery>(context, aspect: aspect)?.data; |
1247 | } |
1248 | |
1249 | /// Returns [MediaQueryData.size] from the nearest [MediaQuery] ancestor or |
1250 | /// throws an exception, if no such ancestor exists. |
1251 | /// |
1252 | /// Use of this method will cause the given [context] to rebuild any time that |
1253 | /// the [MediaQueryData.size] property of the ancestor [MediaQuery] changes. |
1254 | /// |
1255 | /// {@template flutter.widgets.media_query.MediaQuery.dontUseOf} |
1256 | /// Prefer using this function over getting the attribute directly from the |
1257 | /// [MediaQueryData] returned from [of], because using this function will only |
1258 | /// rebuild the `context` when this specific attribute changes, not when _any_ |
1259 | /// attribute changes. |
1260 | /// {@endtemplate} |
1261 | static Size sizeOf(BuildContext context) => _of(context, _MediaQueryAspect.size).size; |
1262 | |
1263 | /// Returns [MediaQueryData.size] from the nearest [MediaQuery] ancestor or |
1264 | /// null, if no such ancestor exists. |
1265 | /// |
1266 | /// Use of this method will cause the given [context] to rebuild any time that |
1267 | /// the [MediaQueryData.size] property of the ancestor [MediaQuery] changes. |
1268 | /// |
1269 | /// {@template flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1270 | /// Prefer using this function over getting the attribute directly from the |
1271 | /// [MediaQueryData] returned from [maybeOf], because using this function will |
1272 | /// only rebuild the `context` when this specific attribute changes, not when |
1273 | /// _any_ attribute changes. |
1274 | /// {@endtemplate} |
1275 | static Size? maybeSizeOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.size)?.size; |
1276 | |
1277 | /// Returns [MediaQueryData.orientation] for the nearest [MediaQuery] ancestor or |
1278 | /// throws an exception, if no such ancestor exists. |
1279 | /// |
1280 | /// Use of this method will cause the given [context] to rebuild any time that |
1281 | /// the [MediaQueryData.orientation] property of the ancestor [MediaQuery] changes. |
1282 | /// |
1283 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1284 | static Orientation orientationOf(BuildContext context) => _of(context, _MediaQueryAspect.orientation).orientation; |
1285 | |
1286 | /// Returns [MediaQueryData.orientation] for the nearest [MediaQuery] ancestor or |
1287 | /// null, if no such ancestor exists. |
1288 | /// |
1289 | /// Use of this method will cause the given [context] to rebuild any time that |
1290 | /// the [MediaQueryData.orientation] property of the ancestor [MediaQuery] changes. |
1291 | /// |
1292 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1293 | static Orientation? maybeOrientationOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.orientation)?.orientation; |
1294 | |
1295 | /// Returns [MediaQueryData.devicePixelRatio] for the nearest [MediaQuery] ancestor or |
1296 | /// throws an exception, if no such ancestor exists. |
1297 | /// |
1298 | /// Use of this method will cause the given [context] to rebuild any time that |
1299 | /// the [MediaQueryData.devicePixelRatio] property of the ancestor [MediaQuery] changes. |
1300 | /// |
1301 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1302 | static double devicePixelRatioOf(BuildContext context) => _of(context, _MediaQueryAspect.devicePixelRatio).devicePixelRatio; |
1303 | |
1304 | /// Returns [MediaQueryData.devicePixelRatio] for the nearest [MediaQuery] ancestor or |
1305 | /// null, if no such ancestor exists. |
1306 | /// |
1307 | /// Use of this method will cause the given [context] to rebuild any time that |
1308 | /// the [MediaQueryData.devicePixelRatio] property of the ancestor [MediaQuery] changes. |
1309 | /// |
1310 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1311 | static double? maybeDevicePixelRatioOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.devicePixelRatio)?.devicePixelRatio; |
1312 | |
1313 | /// Deprecated. Will be removed in a future version of Flutter. Use |
1314 | /// [maybeTextScalerOf] instead. |
1315 | /// |
1316 | /// Returns [MediaQueryData.textScaleFactor] for the nearest [MediaQuery] ancestor or |
1317 | /// 1.0, if no such ancestor exists. |
1318 | /// |
1319 | /// Use of this method will cause the given [context] to rebuild any time that |
1320 | /// the [MediaQueryData.textScaleFactor] property of the ancestor [MediaQuery] changes. |
1321 | /// |
1322 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1323 | @Deprecated( |
1324 | 'Use textScalerOf instead. ' |
1325 | 'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. ' |
1326 | 'This feature was deprecated after v3.12.0-2.0.pre.' , |
1327 | ) |
1328 | static double textScaleFactorOf(BuildContext context) => maybeTextScaleFactorOf(context) ?? 1.0; |
1329 | |
1330 | /// Deprecated. Will be removed in a future version of Flutter. Use |
1331 | /// [maybeTextScalerOf] instead. |
1332 | /// |
1333 | /// Returns [MediaQueryData.textScaleFactor] for the nearest [MediaQuery] ancestor or |
1334 | /// null, if no such ancestor exists. |
1335 | /// |
1336 | /// Use of this method will cause the given [context] to rebuild any time that |
1337 | /// the [MediaQueryData.textScaleFactor] property of the ancestor [MediaQuery] |
1338 | /// changes. |
1339 | /// |
1340 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1341 | @Deprecated( |
1342 | 'Use maybeTextScalerOf instead. ' |
1343 | 'Use of textScaleFactor was deprecated in preparation for the upcoming nonlinear text scaling support. ' |
1344 | 'This feature was deprecated after v3.12.0-2.0.pre.' , |
1345 | ) |
1346 | static double? maybeTextScaleFactorOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.textScaleFactor)?.textScaleFactor; |
1347 | |
1348 | /// Returns the [MediaQueryData.textScaler] for the nearest [MediaQuery] |
1349 | /// ancestor or [TextScaler.noScaling] if no such ancestor exists. |
1350 | /// |
1351 | /// Use of this method will cause the given [context] to rebuild any time that |
1352 | /// the [MediaQueryData.textScaler] property of the ancestor [MediaQuery] |
1353 | /// changes. |
1354 | /// |
1355 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1356 | static TextScaler textScalerOf(BuildContext context) => maybeTextScalerOf(context) ?? TextScaler.noScaling; |
1357 | |
1358 | /// Returns the [MediaQueryData.textScaler] for the nearest [MediaQuery] |
1359 | /// ancestor or null if no such ancestor exists. |
1360 | /// |
1361 | /// Use of this method will cause the given [context] to rebuild any time that |
1362 | /// the [MediaQueryData.textScaler] property of the ancestor [MediaQuery] |
1363 | /// changes. |
1364 | /// |
1365 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1366 | static TextScaler? maybeTextScalerOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.textScaler)?.textScaler; |
1367 | |
1368 | /// Returns [MediaQueryData.platformBrightness] for the nearest [MediaQuery] |
1369 | /// ancestor or [Brightness.light], if no such ancestor exists. |
1370 | /// |
1371 | /// Use of this method will cause the given [context] to rebuild any time that |
1372 | /// the [MediaQueryData.platformBrightness] property of the ancestor |
1373 | /// [MediaQuery] changes. |
1374 | /// |
1375 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1376 | static Brightness platformBrightnessOf(BuildContext context) => maybePlatformBrightnessOf(context) ?? Brightness.light; |
1377 | |
1378 | /// Returns [MediaQueryData.platformBrightness] for the nearest [MediaQuery] |
1379 | /// ancestor or null, if no such ancestor exists. |
1380 | /// |
1381 | /// Use of this method will cause the given [context] to rebuild any time that |
1382 | /// the [MediaQueryData.platformBrightness] property of the ancestor |
1383 | /// [MediaQuery] changes. |
1384 | /// |
1385 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1386 | static Brightness? maybePlatformBrightnessOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.platformBrightness)?.platformBrightness; |
1387 | |
1388 | /// Returns [MediaQueryData.padding] for the nearest [MediaQuery] ancestor or |
1389 | /// throws an exception, if no such ancestor exists. |
1390 | /// |
1391 | /// Use of this method will cause the given [context] to rebuild any time that |
1392 | /// the [MediaQueryData.padding] property of the ancestor [MediaQuery] |
1393 | /// changes. |
1394 | /// |
1395 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1396 | static EdgeInsets paddingOf(BuildContext context) => _of(context, _MediaQueryAspect.padding).padding; |
1397 | |
1398 | /// Returns [MediaQueryData.padding] for the nearest [MediaQuery] ancestor |
1399 | /// or null, if no such ancestor exists. |
1400 | /// |
1401 | /// Use of this method will cause the given [context] to rebuild any time that |
1402 | /// the [MediaQueryData.padding] property of the ancestor [MediaQuery] |
1403 | /// changes. |
1404 | /// |
1405 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1406 | static EdgeInsets? maybePaddingOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.padding)?.padding; |
1407 | |
1408 | /// Returns [MediaQueryData.viewInsets] for the nearest [MediaQuery] ancestor |
1409 | /// or throws an exception, if no such ancestor exists. |
1410 | /// |
1411 | /// Use of this method will cause the given [context] to rebuild any time that |
1412 | /// the [MediaQueryData.viewInsets] property of the ancestor [MediaQuery] |
1413 | /// changes. |
1414 | /// |
1415 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1416 | static EdgeInsets viewInsetsOf(BuildContext context) => _of(context, _MediaQueryAspect.viewInsets).viewInsets; |
1417 | |
1418 | /// Returns [MediaQueryData.viewInsets] for the nearest [MediaQuery] ancestor |
1419 | /// or null, if no such ancestor exists. |
1420 | /// |
1421 | /// Use of this method will cause the given [context] to rebuild any time that |
1422 | /// the [MediaQueryData.viewInsets] property of the ancestor [MediaQuery] |
1423 | /// changes. |
1424 | /// |
1425 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1426 | static EdgeInsets? maybeViewInsetsOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.viewInsets)?.viewInsets; |
1427 | |
1428 | /// Returns [MediaQueryData.systemGestureInsets] for the nearest [MediaQuery] |
1429 | /// ancestor or throws an exception, if no such ancestor exists. |
1430 | /// |
1431 | /// Use of this method will cause the given [context] to rebuild any time that |
1432 | /// the [MediaQueryData.systemGestureInsets] property of the ancestor |
1433 | /// [MediaQuery] changes. |
1434 | /// |
1435 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1436 | static EdgeInsets systemGestureInsetsOf(BuildContext context) => _of(context, _MediaQueryAspect.systemGestureInsets).systemGestureInsets; |
1437 | |
1438 | /// Returns [MediaQueryData.systemGestureInsets] for the nearest [MediaQuery] |
1439 | /// ancestor or null, if no such ancestor exists. |
1440 | /// |
1441 | /// Use of this method will cause the given [context] to rebuild any time that |
1442 | /// the [MediaQueryData.systemGestureInsets] property of the ancestor |
1443 | /// [MediaQuery] changes. |
1444 | /// |
1445 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1446 | static EdgeInsets? maybeSystemGestureInsetsOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.systemGestureInsets)?.systemGestureInsets; |
1447 | |
1448 | /// Returns [MediaQueryData.viewPadding] for the nearest [MediaQuery] ancestor |
1449 | /// or throws an exception, if no such ancestor exists. |
1450 | /// |
1451 | /// Use of this method will cause the given [context] to rebuild any time that |
1452 | /// the [MediaQueryData.viewPadding] property of the ancestor [MediaQuery] |
1453 | /// changes. |
1454 | /// |
1455 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1456 | static EdgeInsets viewPaddingOf(BuildContext context) => _of(context, _MediaQueryAspect.viewPadding).viewPadding; |
1457 | |
1458 | /// Returns [MediaQueryData.viewPadding] for the nearest [MediaQuery] ancestor |
1459 | /// or null, if no such ancestor exists. |
1460 | /// |
1461 | /// Use of this method will cause the given [context] to rebuild any time that |
1462 | /// the [MediaQueryData.viewPadding] property of the ancestor [MediaQuery] |
1463 | /// changes. |
1464 | /// |
1465 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1466 | static EdgeInsets? maybeViewPaddingOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.viewPadding)?.viewPadding; |
1467 | |
1468 | /// Returns [MediaQueryData.alwaysUse24HourFormat] for the nearest |
1469 | /// [MediaQuery] ancestor or throws an exception, if no such ancestor exists. |
1470 | /// |
1471 | /// Use of this method will cause the given [context] to rebuild any time that |
1472 | /// the [MediaQueryData.alwaysUse24HourFormat] property of the ancestor |
1473 | /// [MediaQuery] changes. |
1474 | /// |
1475 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1476 | static bool alwaysUse24HourFormatOf(BuildContext context) => _of(context, _MediaQueryAspect.alwaysUse24HourFormat).alwaysUse24HourFormat; |
1477 | |
1478 | /// Returns [MediaQueryData.alwaysUse24HourFormat] for the nearest |
1479 | /// [MediaQuery] ancestor or null, if no such ancestor exists. |
1480 | /// |
1481 | /// Use of this method will cause the given [context] to rebuild any time that |
1482 | /// the [MediaQueryData.alwaysUse24HourFormat] property of the ancestor |
1483 | /// [MediaQuery] changes. |
1484 | /// |
1485 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1486 | static bool? maybeAlwaysUse24HourFormatOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.alwaysUse24HourFormat)?.alwaysUse24HourFormat; |
1487 | |
1488 | /// Returns [MediaQueryData.accessibleNavigation] for the nearest [MediaQuery] |
1489 | /// ancestor or throws an exception, if no such ancestor exists. |
1490 | /// |
1491 | /// Use of this method will cause the given [context] to rebuild any time that |
1492 | /// the [MediaQueryData.accessibleNavigation] property of the ancestor |
1493 | /// [MediaQuery] changes. |
1494 | /// |
1495 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1496 | static bool accessibleNavigationOf(BuildContext context) => _of(context, _MediaQueryAspect.accessibleNavigation).accessibleNavigation; |
1497 | |
1498 | /// Returns [MediaQueryData.accessibleNavigation] for the nearest [MediaQuery] |
1499 | /// ancestor or null, if no such ancestor exists. |
1500 | /// |
1501 | /// Use of this method will cause the given [context] to rebuild any time that |
1502 | /// the [MediaQueryData.accessibleNavigation] property of the ancestor |
1503 | /// [MediaQuery] changes. |
1504 | /// |
1505 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1506 | static bool? maybeAccessibleNavigationOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.accessibleNavigation)?.accessibleNavigation; |
1507 | |
1508 | /// Returns [MediaQueryData.invertColors] for the nearest [MediaQuery] |
1509 | /// ancestor or throws an exception, if no such ancestor exists. |
1510 | /// |
1511 | /// Use of this method will cause the given [context] to rebuild any time that |
1512 | /// the [MediaQueryData.invertColors] property of the ancestor [MediaQuery] |
1513 | /// changes. |
1514 | /// |
1515 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1516 | static bool invertColorsOf(BuildContext context) => _of(context, _MediaQueryAspect.invertColors).invertColors; |
1517 | |
1518 | /// Returns [MediaQueryData.invertColors] for the nearest [MediaQuery] |
1519 | /// ancestor or null, if no such ancestor exists. |
1520 | /// |
1521 | /// Use of this method will cause the given [context] to rebuild any time that |
1522 | /// the [MediaQueryData.invertColors] property of the ancestor [MediaQuery] |
1523 | /// changes. |
1524 | /// |
1525 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1526 | static bool? maybeInvertColorsOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.invertColors)?.invertColors; |
1527 | |
1528 | /// Returns [MediaQueryData.highContrast] for the nearest [MediaQuery] |
1529 | /// ancestor or false, if no such ancestor exists. |
1530 | /// |
1531 | /// Use of this method will cause the given [context] to rebuild any time that |
1532 | /// the [MediaQueryData.highContrast] property of the ancestor [MediaQuery] |
1533 | /// changes. |
1534 | /// |
1535 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1536 | static bool highContrastOf(BuildContext context) => maybeHighContrastOf(context) ?? false; |
1537 | |
1538 | /// Returns [MediaQueryData.highContrast] for the nearest [MediaQuery] |
1539 | /// ancestor or null, if no such ancestor exists. |
1540 | /// |
1541 | /// Use of this method will cause the given [context] to rebuild any time that |
1542 | /// the [MediaQueryData.highContrast] property of the ancestor [MediaQuery] |
1543 | /// changes. |
1544 | /// |
1545 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1546 | static bool? maybeHighContrastOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.highContrast)?.highContrast; |
1547 | |
1548 | /// Returns [MediaQueryData.onOffSwitchLabels] for the nearest [MediaQuery] |
1549 | /// ancestor or false, if no such ancestor exists. |
1550 | /// |
1551 | /// Use of this method will cause the given [context] to rebuild any time that |
1552 | /// the [MediaQueryData.onOffSwitchLabels] property of the ancestor |
1553 | /// [MediaQuery] changes. |
1554 | /// |
1555 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1556 | static bool onOffSwitchLabelsOf(BuildContext context) => maybeOnOffSwitchLabelsOf(context) ?? false; |
1557 | |
1558 | /// Returns [MediaQueryData.onOffSwitchLabels] for the nearest [MediaQuery] |
1559 | /// ancestor or null, if no such ancestor exists. |
1560 | /// |
1561 | /// Use of this method will cause the given [context] to rebuild any time that |
1562 | /// the [MediaQueryData.onOffSwitchLabels] property of the ancestor |
1563 | /// [MediaQuery] changes. |
1564 | /// |
1565 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1566 | static bool? maybeOnOffSwitchLabelsOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.onOffSwitchLabels)?.onOffSwitchLabels; |
1567 | |
1568 | /// Returns [MediaQueryData.disableAnimations] for the nearest [MediaQuery] |
1569 | /// ancestor or false, if no such ancestor exists. |
1570 | /// |
1571 | /// Use of this method will cause the given [context] to rebuild any time that |
1572 | /// the [MediaQueryData.disableAnimations] property of the ancestor |
1573 | /// [MediaQuery] changes. |
1574 | /// |
1575 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1576 | static bool disableAnimationsOf(BuildContext context) => _of(context, _MediaQueryAspect.disableAnimations).disableAnimations; |
1577 | |
1578 | /// Returns [MediaQueryData.disableAnimations] for the nearest [MediaQuery] |
1579 | /// ancestor or null, if no such ancestor exists. |
1580 | /// |
1581 | /// Use of this method will cause the given [context] to rebuild any time that |
1582 | /// the [MediaQueryData.disableAnimations] property of the ancestor |
1583 | /// [MediaQuery] changes. |
1584 | /// |
1585 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1586 | static bool? maybeDisableAnimationsOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.disableAnimations)?.disableAnimations; |
1587 | |
1588 | /// Returns the [MediaQueryData.boldText] accessibility setting for the |
1589 | /// nearest [MediaQuery] ancestor or false, if no such ancestor exists. |
1590 | /// |
1591 | /// Use of this method will cause the given [context] to rebuild any time that |
1592 | /// the [MediaQueryData.boldText] property of the ancestor [MediaQuery] |
1593 | /// changes. |
1594 | /// |
1595 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1596 | static bool boldTextOf(BuildContext context) => maybeBoldTextOf(context) ?? false; |
1597 | |
1598 | /// Returns the [MediaQueryData.boldText] accessibility setting for the |
1599 | /// nearest [MediaQuery] ancestor or null, if no such ancestor exists. |
1600 | /// |
1601 | /// Use of this method will cause the given [context] to rebuild any time that |
1602 | /// the [MediaQueryData.boldText] property of the ancestor [MediaQuery] |
1603 | /// changes. |
1604 | /// |
1605 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1606 | static bool? maybeBoldTextOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.boldText)?.boldText; |
1607 | |
1608 | /// Returns [MediaQueryData.navigationMode] for the nearest [MediaQuery] |
1609 | /// ancestor or throws an exception, if no such ancestor exists. |
1610 | /// |
1611 | /// Use of this method will cause the given [context] to rebuild any time that |
1612 | /// the [MediaQueryData.navigationMode] property of the ancestor [MediaQuery] |
1613 | /// changes. |
1614 | /// |
1615 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1616 | static NavigationMode navigationModeOf(BuildContext context) => _of(context, _MediaQueryAspect.navigationMode).navigationMode; |
1617 | |
1618 | /// Returns [MediaQueryData.navigationMode] for the nearest [MediaQuery] |
1619 | /// ancestor or null, if no such ancestor exists. |
1620 | /// |
1621 | /// Use of this method will cause the given [context] to rebuild any time that |
1622 | /// the [MediaQueryData.navigationMode] property of the ancestor [MediaQuery] |
1623 | /// changes. |
1624 | /// |
1625 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1626 | static NavigationMode? maybeNavigationModeOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.navigationMode)?.navigationMode; |
1627 | |
1628 | /// Returns [MediaQueryData.gestureSettings] for the nearest [MediaQuery] |
1629 | /// ancestor or throws an exception, if no such ancestor exists. |
1630 | /// |
1631 | /// Use of this method will cause the given [context] to rebuild any time that |
1632 | /// the [MediaQueryData.gestureSettings] property of the ancestor [MediaQuery] |
1633 | /// changes. |
1634 | /// |
1635 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1636 | static DeviceGestureSettings gestureSettingsOf(BuildContext context) => _of(context, _MediaQueryAspect.gestureSettings).gestureSettings; |
1637 | |
1638 | /// Returns [MediaQueryData.gestureSettings] for the nearest [MediaQuery] |
1639 | /// ancestor or null, if no such ancestor exists. |
1640 | /// |
1641 | /// Use of this method will cause the given [context] to rebuild any time that |
1642 | /// the [MediaQueryData.gestureSettings] property of the ancestor [MediaQuery] |
1643 | /// changes. |
1644 | /// |
1645 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1646 | static DeviceGestureSettings? maybeGestureSettingsOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.gestureSettings)?.gestureSettings; |
1647 | |
1648 | /// Returns [MediaQueryData.displayFeatures] for the nearest [MediaQuery] |
1649 | /// ancestor or throws an exception, if no such ancestor exists. |
1650 | /// |
1651 | /// Use of this method will cause the given [context] to rebuild any time that |
1652 | /// the [MediaQueryData.displayFeatures] property of the ancestor [MediaQuery] |
1653 | /// changes. |
1654 | /// |
1655 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1656 | static List<ui.DisplayFeature> displayFeaturesOf(BuildContext context) => _of(context, _MediaQueryAspect.displayFeatures).displayFeatures; |
1657 | |
1658 | /// Returns [MediaQueryData.displayFeatures] for the nearest [MediaQuery] |
1659 | /// ancestor or null, if no such ancestor exists. |
1660 | /// |
1661 | /// Use of this method will cause the given [context] to rebuild any time that |
1662 | /// the [MediaQueryData.displayFeatures] property of the ancestor [MediaQuery] |
1663 | /// changes. |
1664 | /// |
1665 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1666 | static List<ui.DisplayFeature>? maybeDisplayFeaturesOf(BuildContext context) => _maybeOf(context, _MediaQueryAspect.displayFeatures)?.displayFeatures; |
1667 | |
1668 | /// Returns [MediaQueryData.supportsShowingSystemContextMenu] for the nearest |
1669 | /// [MediaQuery] ancestor or throws an exception, if no such ancestor exists. |
1670 | /// |
1671 | /// Use of this method will cause the given [context] to rebuild any time that |
1672 | /// the [MediaQueryData.supportsShowingSystemContextMenu] property of the |
1673 | /// ancestor [MediaQuery] changes. |
1674 | /// |
1675 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseOf} |
1676 | static bool supportsShowingSystemContextMenu(BuildContext context) => _of(context, _MediaQueryAspect.supportsShowingSystemContextMenu).supportsShowingSystemContextMenu; |
1677 | |
1678 | /// Returns [MediaQueryData.supportsShowingSystemContextMenu] for the nearest |
1679 | /// [MediaQuery] ancestor or null, if no such ancestor exists. |
1680 | /// |
1681 | /// Use of this method will cause the given [context] to rebuild any time that |
1682 | /// the [MediaQueryData.supportsShowingSystemContextMenu] property of the |
1683 | /// ancestor [MediaQuery] changes. |
1684 | /// |
1685 | /// {@macro flutter.widgets.media_query.MediaQuery.dontUseMaybeOf} |
1686 | static bool? maybeSupportsShowingSystemContextMenu(BuildContext context) => _maybeOf(context, _MediaQueryAspect.supportsShowingSystemContextMenu)?.supportsShowingSystemContextMenu; |
1687 | |
1688 | @override |
1689 | bool updateShouldNotify(MediaQuery oldWidget) => data != oldWidget.data; |
1690 | |
1691 | @override |
1692 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
1693 | super.debugFillProperties(properties); |
1694 | properties.add(DiagnosticsProperty<MediaQueryData>('data' , data, showName: false)); |
1695 | } |
1696 | |
1697 | @override |
1698 | bool updateShouldNotifyDependent(MediaQuery oldWidget, Set<Object> dependencies) { |
1699 | return dependencies.any((Object dependency) => dependency is _MediaQueryAspect && switch (dependency) { |
1700 | _MediaQueryAspect.size => data.size != oldWidget.data.size, |
1701 | _MediaQueryAspect.orientation => data.orientation != oldWidget.data.orientation, |
1702 | _MediaQueryAspect.devicePixelRatio => data.devicePixelRatio != oldWidget.data.devicePixelRatio, |
1703 | _MediaQueryAspect.textScaleFactor => data.textScaleFactor != oldWidget.data.textScaleFactor, |
1704 | _MediaQueryAspect.textScaler => data.textScaler != oldWidget.data.textScaler, |
1705 | _MediaQueryAspect.platformBrightness => data.platformBrightness != oldWidget.data.platformBrightness, |
1706 | _MediaQueryAspect.padding => data.padding != oldWidget.data.padding, |
1707 | _MediaQueryAspect.viewInsets => data.viewInsets != oldWidget.data.viewInsets, |
1708 | _MediaQueryAspect.viewPadding => data.viewPadding != oldWidget.data.viewPadding, |
1709 | _MediaQueryAspect.invertColors => data.invertColors != oldWidget.data.invertColors, |
1710 | _MediaQueryAspect.highContrast => data.highContrast != oldWidget.data.highContrast, |
1711 | _MediaQueryAspect.onOffSwitchLabels => data.onOffSwitchLabels != oldWidget.data.onOffSwitchLabels, |
1712 | _MediaQueryAspect.disableAnimations => data.disableAnimations != oldWidget.data.disableAnimations, |
1713 | _MediaQueryAspect.boldText => data.boldText != oldWidget.data.boldText, |
1714 | _MediaQueryAspect.navigationMode => data.navigationMode != oldWidget.data.navigationMode, |
1715 | _MediaQueryAspect.gestureSettings => data.gestureSettings != oldWidget.data.gestureSettings, |
1716 | _MediaQueryAspect.displayFeatures => data.displayFeatures != oldWidget.data.displayFeatures, |
1717 | _MediaQueryAspect.systemGestureInsets => data.systemGestureInsets != oldWidget.data.systemGestureInsets, |
1718 | _MediaQueryAspect.accessibleNavigation => data.accessibleNavigation != oldWidget.data.accessibleNavigation, |
1719 | _MediaQueryAspect.alwaysUse24HourFormat => data.alwaysUse24HourFormat != oldWidget.data.alwaysUse24HourFormat, |
1720 | _MediaQueryAspect.supportsShowingSystemContextMenu => data.supportsShowingSystemContextMenu != oldWidget.data.supportsShowingSystemContextMenu, |
1721 | }); |
1722 | } |
1723 | } |
1724 | |
1725 | /// Describes the navigation mode to be set by a [MediaQuery] widget. |
1726 | /// |
1727 | /// The different modes indicate the type of navigation to be used in a widget |
1728 | /// subtree for those widgets sensitive to it. |
1729 | /// |
1730 | /// Use `MediaQuery.navigationModeOf(context)` to determine the navigation mode |
1731 | /// in effect for the given context. Use a [MediaQuery] widget to set the |
1732 | /// navigation mode for its descendant widgets. |
1733 | enum NavigationMode { |
1734 | /// This indicates a traditional keyboard-and-mouse navigation modality. |
1735 | /// |
1736 | /// This navigation mode is where the arrow keys can be used for secondary |
1737 | /// modification operations, like moving sliders or cursors, and disabled |
1738 | /// controls will lose focus and not be traversable. |
1739 | traditional, |
1740 | |
1741 | /// This indicates a directional-based navigation mode. |
1742 | /// |
1743 | /// This navigation mode indicates that arrow keys should be reserved for |
1744 | /// navigation operations, and secondary modifications operations, like moving |
1745 | /// sliders or cursors, will use alternative bindings or be disabled. |
1746 | /// |
1747 | /// Some behaviors are also affected by this mode. For instance, disabled |
1748 | /// controls will retain focus when disabled, and will be able to receive |
1749 | /// focus (although they remain disabled) when traversed. |
1750 | directional, |
1751 | } |
1752 | |
1753 | class _MediaQueryFromView extends StatefulWidget { |
1754 | const _MediaQueryFromView({ |
1755 | super.key, |
1756 | required this.view, |
1757 | this.ignoreParentData = false, |
1758 | required this.child, |
1759 | }); |
1760 | |
1761 | final FlutterView view; |
1762 | final bool ignoreParentData; |
1763 | final Widget child; |
1764 | |
1765 | @override |
1766 | State<_MediaQueryFromView> createState() => _MediaQueryFromViewState(); |
1767 | } |
1768 | |
1769 | class _MediaQueryFromViewState extends State<_MediaQueryFromView> with WidgetsBindingObserver { |
1770 | MediaQueryData? _parentData; |
1771 | MediaQueryData? _data; |
1772 | |
1773 | @override |
1774 | void initState() { |
1775 | super.initState(); |
1776 | WidgetsBinding.instance.addObserver(this); |
1777 | } |
1778 | |
1779 | @override |
1780 | void didChangeDependencies() { |
1781 | super.didChangeDependencies(); |
1782 | _updateParentData(); |
1783 | _updateData(); |
1784 | assert(_data != null); |
1785 | } |
1786 | |
1787 | @override |
1788 | void didUpdateWidget(_MediaQueryFromView oldWidget) { |
1789 | super.didUpdateWidget(oldWidget); |
1790 | if (widget.ignoreParentData != oldWidget.ignoreParentData) { |
1791 | _updateParentData(); |
1792 | } |
1793 | if (_data == null || oldWidget.view != widget.view) { |
1794 | _updateData(); |
1795 | } |
1796 | assert(_data != null); |
1797 | } |
1798 | |
1799 | void _updateParentData() { |
1800 | _parentData = widget.ignoreParentData ? null : MediaQuery.maybeOf(context); |
1801 | _data = null; // _updateData must be called again after changing parent data. |
1802 | } |
1803 | |
1804 | void _updateData() { |
1805 | final MediaQueryData newData = MediaQueryData.fromView(widget.view, platformData: _parentData); |
1806 | if (newData != _data) { |
1807 | setState(() { |
1808 | _data = newData; |
1809 | }); |
1810 | } |
1811 | } |
1812 | |
1813 | @override |
1814 | void didChangeAccessibilityFeatures() { |
1815 | // If we have a parent, it dictates our accessibility features. If we don't |
1816 | // have a parent, we get our accessibility features straight from the |
1817 | // PlatformDispatcher and need to update our data in response to the |
1818 | // PlatformDispatcher changing its accessibility features setting. |
1819 | if (_parentData == null) { |
1820 | _updateData(); |
1821 | } |
1822 | } |
1823 | |
1824 | @override |
1825 | void didChangeMetrics() { |
1826 | _updateData(); |
1827 | } |
1828 | |
1829 | @override |
1830 | void didChangeTextScaleFactor() { |
1831 | // If we have a parent, it dictates our text scale factor. If we don't have |
1832 | // a parent, we get our text scale factor from the PlatformDispatcher and |
1833 | // need to update our data in response to the PlatformDispatcher changing |
1834 | // its text scale factor setting. |
1835 | if (_parentData == null) { |
1836 | _updateData(); |
1837 | } |
1838 | } |
1839 | |
1840 | @override |
1841 | void didChangePlatformBrightness() { |
1842 | // If we have a parent, it dictates our platform brightness. If we don't |
1843 | // have a parent, we get our platform brightness from the PlatformDispatcher |
1844 | // and need to update our data in response to the PlatformDispatcher |
1845 | // changing its platform brightness setting. |
1846 | if (_parentData == null) { |
1847 | _updateData(); |
1848 | } |
1849 | } |
1850 | |
1851 | @override |
1852 | void dispose() { |
1853 | WidgetsBinding.instance.removeObserver(this); |
1854 | super.dispose(); |
1855 | } |
1856 | |
1857 | @override |
1858 | Widget build(BuildContext context) { |
1859 | MediaQueryData effectiveData = _data!; |
1860 | // If we get our platformBrightness from the PlatformDispatcher (i.e. we have no parentData) replace it |
1861 | // with the debugBrightnessOverride in non-release mode. |
1862 | if (!kReleaseMode && _parentData == null && effectiveData.platformBrightness != debugBrightnessOverride) { |
1863 | effectiveData = effectiveData.copyWith(platformBrightness: debugBrightnessOverride); |
1864 | } |
1865 | return MediaQuery( |
1866 | data: effectiveData, |
1867 | child: widget.child, |
1868 | ); |
1869 | } |
1870 | } |
1871 | |
1872 | const TextScaler _kUnspecifiedTextScaler = _UnspecifiedTextScaler(); |
1873 | // TODO(LongCatIsLooong): Remove once `MediaQueryData.textScaleFactor` is |
1874 | // removed: https://github.com/flutter/flutter/issues/128825. |
1875 | class _UnspecifiedTextScaler implements TextScaler { |
1876 | const _UnspecifiedTextScaler(); |
1877 | |
1878 | @override |
1879 | TextScaler clamp({double minScaleFactor = 0, double maxScaleFactor = double.infinity}) => throw UnimplementedError(); |
1880 | |
1881 | @override |
1882 | double scale(double fontSize) => throw UnimplementedError(); |
1883 | |
1884 | @override |
1885 | double get textScaleFactor => throw UnimplementedError(); |
1886 | } |
1887 | |