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