Unverified Commit 3b741047 authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

Add MediaQuery.systemGestureInsets to support Android Q (#37416)

* Wire Window.systemGestureInsets to MediaQuery.systemGestureInsets

* Add systemGestureInsets property to TestWindow
parent 3f6bac66
...@@ -93,6 +93,7 @@ class MediaQueryData { ...@@ -93,6 +93,7 @@ class MediaQueryData {
this.platformBrightness = Brightness.light, this.platformBrightness = Brightness.light,
this.padding = EdgeInsets.zero, this.padding = EdgeInsets.zero,
this.viewInsets = EdgeInsets.zero, this.viewInsets = EdgeInsets.zero,
this.systemGestureInsets = EdgeInsets.zero,
this.viewPadding = EdgeInsets.zero, this.viewPadding = EdgeInsets.zero,
this.physicalDepth = double.maxFinite, this.physicalDepth = double.maxFinite,
this.alwaysUse24HourFormat = false, this.alwaysUse24HourFormat = false,
...@@ -117,6 +118,7 @@ class MediaQueryData { ...@@ -117,6 +118,7 @@ class MediaQueryData {
padding = EdgeInsets.fromWindowPadding(window.padding, window.devicePixelRatio), padding = EdgeInsets.fromWindowPadding(window.padding, window.devicePixelRatio),
viewPadding = EdgeInsets.fromWindowPadding(window.viewPadding, window.devicePixelRatio), viewPadding = EdgeInsets.fromWindowPadding(window.viewPadding, window.devicePixelRatio),
viewInsets = EdgeInsets.fromWindowPadding(window.viewInsets, window.devicePixelRatio), viewInsets = EdgeInsets.fromWindowPadding(window.viewInsets, window.devicePixelRatio),
systemGestureInsets = EdgeInsets.fromWindowPadding(window.systemGestureInsets, window.devicePixelRatio),
physicalDepth = window.physicalDepth, physicalDepth = window.physicalDepth,
accessibleNavigation = window.accessibilityFeatures.accessibleNavigation, accessibleNavigation = window.accessibilityFeatures.accessibleNavigation,
invertColors = window.accessibilityFeatures.invertColors, invertColors = window.accessibilityFeatures.invertColors,
...@@ -215,6 +217,61 @@ class MediaQueryData { ...@@ -215,6 +217,61 @@ class MediaQueryData {
/// property and how it relates to [padding] and [viewInsets]. /// property and how it relates to [padding] and [viewInsets].
final EdgeInsets viewPadding; final EdgeInsets viewPadding;
/// The areas along the edges of the display where the system consumes
/// certain input events and blocks delivery of those events to the app.
///
/// Starting with Android Q, simple swipe gestures that start within the
/// [systemGestureInsets] areas are used by the system for page navigation
/// and may not be delivered to the app. Taps and swipe gestures that begin
/// with a long-press are delivered to the app, but simple press-drag-release
/// swipe gestures which begin within the area defined by [systemGestureInsets]
/// may not be.
///
/// Apps should avoid locating gesture detectors within the system gesture
/// insets area. Apps should feel free to put visual elements within
/// this area.
///
/// This property is currently only expected to be set to a non-default value
/// on Android starting with version Q.
///
/// {@tool snippet --template=stateful_widget_material}
///
/// For apps that might be deployed on Android Q devices with full gesture
/// navigation enabled, use [MediaQuery.systemGestureInsets] with [Padding]
/// to avoid having the left and right edges of the [Slider] from appearing
/// within the area reserved for system gesture navigation.
///
/// By default, [Slider]s expand to fill the available width. So, we pad the
/// left and right sides.
///
/// ```dart
/// double _currentValue = 0.2;
///
/// @override
/// Widget build(BuildContext context) {
/// EdgeInsets systemGestureInsets = MediaQuery.of(context).systemGestureInsets;
/// return Scaffold(
/// appBar: AppBar(title: Text('Pad Slider to avoid systemGestureInsets')),
/// body: Padding(
/// padding: EdgeInsets.only( // only left and right padding are needed here
/// left: systemGestureInsets.left,
/// right: systemGestureInsets.right,
/// ),
/// child: Slider(
/// value: _currentValue.toDouble(),
/// onChanged: (double newValue) {
/// setState(() {
/// _currentValue = newValue;
/// });
/// },
/// ),
/// ),
/// );
/// }
/// ```
/// {@end-tool}
final EdgeInsets systemGestureInsets;
/// The physical depth is the maximum elevation that the Window allows. /// The physical depth is the maximum elevation that the Window allows.
/// ///
/// Physical layers drawn at or above this elevation will have their elevation /// Physical layers drawn at or above this elevation will have their elevation
...@@ -300,6 +357,7 @@ class MediaQueryData { ...@@ -300,6 +357,7 @@ class MediaQueryData {
EdgeInsets padding, EdgeInsets padding,
EdgeInsets viewPadding, EdgeInsets viewPadding,
EdgeInsets viewInsets, EdgeInsets viewInsets,
EdgeInsets systemGestureInsets,
double physicalDepth, double physicalDepth,
bool alwaysUse24HourFormat, bool alwaysUse24HourFormat,
bool highContrast, bool highContrast,
...@@ -316,6 +374,7 @@ class MediaQueryData { ...@@ -316,6 +374,7 @@ class MediaQueryData {
padding: padding ?? this.padding, padding: padding ?? this.padding,
viewPadding: viewPadding ?? this.viewPadding, viewPadding: viewPadding ?? this.viewPadding,
viewInsets: viewInsets ?? this.viewInsets, viewInsets: viewInsets ?? this.viewInsets,
systemGestureInsets: systemGestureInsets ?? this.systemGestureInsets,
physicalDepth: physicalDepth ?? this.physicalDepth, physicalDepth: physicalDepth ?? this.physicalDepth,
alwaysUse24HourFormat: alwaysUse24HourFormat ?? this.alwaysUse24HourFormat, alwaysUse24HourFormat: alwaysUse24HourFormat ?? this.alwaysUse24HourFormat,
invertColors: invertColors ?? this.invertColors, invertColors: invertColors ?? this.invertColors,
......
...@@ -59,6 +59,7 @@ void main() { ...@@ -59,6 +59,7 @@ void main() {
expect(copied.padding, data.padding); expect(copied.padding, data.padding);
expect(copied.viewPadding, data.viewPadding); expect(copied.viewPadding, data.viewPadding);
expect(copied.viewInsets, data.viewInsets); expect(copied.viewInsets, data.viewInsets);
expect(copied.systemGestureInsets, data.systemGestureInsets);
expect(copied.physicalDepth, data.physicalDepth); expect(copied.physicalDepth, data.physicalDepth);
expect(copied.alwaysUse24HourFormat, data.alwaysUse24HourFormat); expect(copied.alwaysUse24HourFormat, data.alwaysUse24HourFormat);
expect(copied.accessibleNavigation, data.accessibleNavigation); expect(copied.accessibleNavigation, data.accessibleNavigation);
...@@ -77,6 +78,7 @@ void main() { ...@@ -77,6 +78,7 @@ void main() {
padding: const EdgeInsets.all(9.10938), padding: const EdgeInsets.all(9.10938),
viewPadding: const EdgeInsets.all(11.24031), viewPadding: const EdgeInsets.all(11.24031),
viewInsets: const EdgeInsets.all(1.67262), viewInsets: const EdgeInsets.all(1.67262),
systemGestureInsets: const EdgeInsets.all(1.5556),
physicalDepth: 120.0, physicalDepth: 120.0,
alwaysUse24HourFormat: true, alwaysUse24HourFormat: true,
accessibleNavigation: true, accessibleNavigation: true,
...@@ -91,6 +93,7 @@ void main() { ...@@ -91,6 +93,7 @@ void main() {
expect(copied.padding, const EdgeInsets.all(9.10938)); expect(copied.padding, const EdgeInsets.all(9.10938));
expect(copied.viewPadding, const EdgeInsets.all(11.24031)); expect(copied.viewPadding, const EdgeInsets.all(11.24031));
expect(copied.viewInsets, const EdgeInsets.all(1.67262)); expect(copied.viewInsets, const EdgeInsets.all(1.67262));
expect(copied.systemGestureInsets, const EdgeInsets.all(1.5556));
expect(copied.physicalDepth, 120.0); expect(copied.physicalDepth, 120.0);
expect(copied.alwaysUse24HourFormat, true); expect(copied.alwaysUse24HourFormat, true);
expect(copied.accessibleNavigation, true); expect(copied.accessibleNavigation, true);
......
...@@ -148,6 +148,20 @@ class TestWindow implements Window { ...@@ -148,6 +148,20 @@ class TestWindow implements Window {
onMetricsChanged(); onMetricsChanged();
} }
@override
WindowPadding get systemGestureInsets => _systemGestureInsetsTestValue ?? _window.systemGestureInsets;
WindowPadding _systemGestureInsetsTestValue;
/// Hides the real system gesture insets and reports the given [systemGestureInsetsTestValue] instead.
set systemGestureInsetsTestValue(WindowPadding systemGestureInsetsTestValue) {
_systemGestureInsetsTestValue = systemGestureInsetsTestValue;
onMetricsChanged();
}
/// Deletes any existing test system gesture insets and returns to using the real system gesture insets.
void clearSystemGestureInsetsTestValue() {
_systemGestureInsetsTestValue = null;
onMetricsChanged();
}
@override @override
VoidCallback get onMetricsChanged => _window.onMetricsChanged; VoidCallback get onMetricsChanged => _window.onMetricsChanged;
@override @override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment