Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
ea1182ef
Unverified
Commit
ea1182ef
authored
Jul 27, 2021
by
Attila Szabó
Committed by
GitHub
Jul 27, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP - Reland "Override MediaQuery for WidgetsApp (#81295)" (#85298)
parent
f8d2615d
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
298 additions
and
85 deletions
+298
-85
app.dart
packages/flutter/lib/src/cupertino/app.dart
+7
-0
app.dart
packages/flutter/lib/src/material/app.dart
+7
-0
app.dart
packages/flutter/lib/src/widgets/app.dart
+29
-85
media_query.dart
packages/flutter/lib/src/widgets/media_query.dart
+120
-0
app_test.dart
packages/flutter/test/cupertino/app_test.dart
+20
-0
app_test.dart
packages/flutter/test/material/app_test.dart
+20
-0
app_test.dart
packages/flutter/test/widgets/app_test.dart
+50
-0
media_query_test.dart
packages/flutter/test/widgets/media_query_test.dart
+45
-0
No files found.
packages/flutter/lib/src/cupertino/app.dart
View file @
ea1182ef
...
...
@@ -170,6 +170,7 @@ class CupertinoApp extends StatefulWidget {
this
.
actions
,
this
.
restorationScopeId
,
this
.
scrollBehavior
,
this
.
useInheritedMediaQuery
=
false
,
})
:
assert
(
routes
!=
null
),
assert
(
navigatorObservers
!=
null
),
assert
(
title
!=
null
),
...
...
@@ -210,6 +211,7 @@ class CupertinoApp extends StatefulWidget {
this
.
actions
,
this
.
restorationScopeId
,
this
.
scrollBehavior
,
this
.
useInheritedMediaQuery
=
false
,
})
:
assert
(
title
!=
null
),
assert
(
showPerformanceOverlay
!=
null
),
assert
(
checkerboardRasterCacheImages
!=
null
),
...
...
@@ -407,6 +409,9 @@ class CupertinoApp extends StatefulWidget {
/// in a subtree.
final
ScrollBehavior
?
scrollBehavior
;
/// {@macro flutter.widgets.widgetsApp.useInheritedMediaQuery}
final
bool
useInheritedMediaQuery
;
@override
State
<
CupertinoApp
>
createState
()
=>
_CupertinoAppState
();
...
...
@@ -530,6 +535,7 @@ class _CupertinoAppState extends State<CupertinoApp> {
shortcuts:
widget
.
shortcuts
,
actions:
widget
.
actions
,
restorationScopeId:
widget
.
restorationScopeId
,
useInheritedMediaQuery:
widget
.
useInheritedMediaQuery
,
);
}
return
WidgetsApp
(
...
...
@@ -564,6 +570,7 @@ class _CupertinoAppState extends State<CupertinoApp> {
shortcuts:
widget
.
shortcuts
,
actions:
widget
.
actions
,
restorationScopeId:
widget
.
restorationScopeId
,
useInheritedMediaQuery:
widget
.
useInheritedMediaQuery
,
);
}
...
...
packages/flutter/lib/src/material/app.dart
View file @
ea1182ef
...
...
@@ -200,6 +200,7 @@ class MaterialApp extends StatefulWidget {
this
.
actions
,
this
.
restorationScopeId
,
this
.
scrollBehavior
,
this
.
useInheritedMediaQuery
=
false
,
})
:
assert
(
routes
!=
null
),
assert
(
navigatorObservers
!=
null
),
assert
(
title
!=
null
),
...
...
@@ -247,6 +248,7 @@ class MaterialApp extends StatefulWidget {
this
.
actions
,
this
.
restorationScopeId
,
this
.
scrollBehavior
,
this
.
useInheritedMediaQuery
=
false
,
})
:
assert
(
routeInformationParser
!=
null
),
assert
(
routerDelegate
!=
null
),
assert
(
title
!=
null
),
...
...
@@ -665,6 +667,9 @@ class MaterialApp extends StatefulWidget {
/// * <https://material.io/design/layout/spacing-methods.html>
final
bool
debugShowMaterialGrid
;
/// {@macro flutter.widgets.widgetsApp.useInheritedMediaQuery}
final
bool
useInheritedMediaQuery
;
@override
State
<
MaterialApp
>
createState
()
=>
_MaterialAppState
();
...
...
@@ -858,6 +863,7 @@ class _MaterialAppState extends State<MaterialApp> {
shortcuts:
widget
.
shortcuts
,
actions:
widget
.
actions
,
restorationScopeId:
widget
.
restorationScopeId
,
useInheritedMediaQuery:
widget
.
useInheritedMediaQuery
,
);
}
...
...
@@ -893,6 +899,7 @@ class _MaterialAppState extends State<MaterialApp> {
shortcuts:
widget
.
shortcuts
,
actions:
widget
.
actions
,
restorationScopeId:
widget
.
restorationScopeId
,
useInheritedMediaQuery:
widget
.
useInheritedMediaQuery
,
);
}
...
...
packages/flutter/lib/src/widgets/app.dart
View file @
ea1182ef
...
...
@@ -236,6 +236,9 @@ typedef InitialRouteListFactory = List<Route<dynamic>> Function(String initialRo
/// It is used by both [MaterialApp] and [CupertinoApp] to implement base
/// functionality for an app.
///
/// Builds a [MediaQuery] using [MediaQuery.fromWindow]. To use an inherited
/// [MediaQuery] instead, set [useInheritedMediaQuery] to true.
///
/// Find references to many of the widgets that [WidgetsApp] wraps in the "See
/// also" section.
///
...
...
@@ -247,6 +250,8 @@ typedef InitialRouteListFactory = List<Route<dynamic>> Function(String initialRo
/// without an explicit style.
/// * [MediaQuery], which establishes a subtree in which media queries resolve
/// to a [MediaQueryData].
/// * [MediaQuery.fromWindow], which builds a [MediaQuery] with data derived
/// from [WidgetsBinding.window].
/// * [Localizations], which defines the [Locale] for its `child`.
/// * [Title], a widget that describes this app in the operating system.
/// * [Navigator], a widget that manages a set of child widgets with a stack
...
...
@@ -327,6 +332,7 @@ class WidgetsApp extends StatefulWidget {
this
.
shortcuts
,
this
.
actions
,
this
.
restorationScopeId
,
this
.
useInheritedMediaQuery
=
false
,
})
:
assert
(
navigatorObservers
!=
null
),
assert
(
routes
!=
null
),
assert
(
...
...
@@ -423,6 +429,7 @@ class WidgetsApp extends StatefulWidget {
this
.
shortcuts
,
this
.
actions
,
this
.
restorationScopeId
,
this
.
useInheritedMediaQuery
=
false
,
})
:
assert
(
routeInformationParser
!=
null
&&
routerDelegate
!=
null
,
...
...
@@ -1111,6 +1118,14 @@ class WidgetsApp extends StatefulWidget {
/// {@endtemplate}
final
String
?
restorationScopeId
;
/// {@template flutter.widgets.widgetsApp.useInheritedMediaQuery}
/// If true, an inherited MediaQuery will be used. If one is not available,
/// or this is false, one will be built from the window.
///
/// Cannot be null, defaults to false.
/// {@endtemplate}
final
bool
useInheritedMediaQuery
;
/// If true, forces the performance overlay to be visible in all instances.
///
/// Used by the `showPerformanceOverlay` observatory extension.
...
...
@@ -1635,6 +1650,19 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
assert
(
_debugCheckLocalizations
(
appLocale
));
Widget
child
=
Localizations
(
locale:
appLocale
,
delegates:
_localizationsDelegates
.
toList
(),
child:
title
,
);
final
MediaQueryData
?
data
=
MediaQuery
.
maybeOf
(
context
);
if
(!
widget
.
useInheritedMediaQuery
||
data
==
null
)
{
child
=
MediaQuery
.
fromWindow
(
child:
child
,
);
}
return
RootRestorationScope
(
restorationId:
widget
.
restorationScopeId
,
child:
Shortcuts
(
...
...
@@ -1648,13 +1676,7 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
child:
DefaultTextEditingActions
(
child:
FocusTraversalGroup
(
policy:
ReadingOrderTraversalPolicy
(),
child:
_MediaQueryFromWindow
(
child:
Localizations
(
locale:
appLocale
,
delegates:
_localizationsDelegates
.
toList
(),
child:
title
,
),
),
child:
child
,
),
),
),
...
...
@@ -1663,81 +1685,3 @@ class _WidgetsAppState extends State<WidgetsApp> with WidgetsBindingObserver {
);
}
}
/// Builds [MediaQuery] from `window` by listening to [WidgetsBinding].
///
/// It is performed in a standalone widget to rebuild **only** [MediaQuery] and
/// its dependents when `window` changes, instead of rebuilding the entire widget tree.
class
_MediaQueryFromWindow
extends
StatefulWidget
{
const
_MediaQueryFromWindow
({
Key
?
key
,
required
this
.
child
})
:
super
(
key:
key
);
final
Widget
child
;
@override
_MediaQueryFromWindowsState
createState
()
=>
_MediaQueryFromWindowsState
();
}
class
_MediaQueryFromWindowsState
extends
State
<
_MediaQueryFromWindow
>
with
WidgetsBindingObserver
{
@override
void
initState
()
{
super
.
initState
();
WidgetsBinding
.
instance
!.
addObserver
(
this
);
}
// ACCESSIBILITY
@override
void
didChangeAccessibilityFeatures
()
{
setState
(()
{
// The properties of window have changed. We use them in our build
// function, so we need setState(), but we don't cache anything locally.
});
}
// METRICS
@override
void
didChangeMetrics
()
{
setState
(()
{
// The properties of window have changed. We use them in our build
// function, so we need setState(), but we don't cache anything locally.
});
}
@override
void
didChangeTextScaleFactor
()
{
setState
(()
{
// The textScaleFactor property of window has changed. We reference
// window in our build function, so we need to call setState(), but
// we don't need to cache anything locally.
});
}
// RENDERING
@override
void
didChangePlatformBrightness
()
{
setState
(()
{
// The platformBrightness property of window has changed. We reference
// window in our build function, so we need to call setState(), but
// we don't need to cache anything locally.
});
}
@override
Widget
build
(
BuildContext
context
)
{
MediaQueryData
data
=
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
!.
window
);
if
(!
kReleaseMode
)
{
data
=
data
.
copyWith
(
platformBrightness:
debugBrightnessOverride
);
}
return
MediaQuery
(
data:
data
,
child:
widget
.
child
,
);
}
@override
void
dispose
()
{
WidgetsBinding
.
instance
!.
removeObserver
(
this
);
super
.
dispose
();
}
}
packages/flutter/lib/src/widgets/media_query.dart
View file @
ea1182ef
...
...
@@ -9,6 +9,7 @@ import 'dart:ui' show Brightness;
import
'package:flutter/foundation.dart'
;
import
'basic.dart'
;
import
'binding.dart'
;
import
'debug.dart'
;
import
'framework.dart'
;
...
...
@@ -787,6 +788,28 @@ class MediaQuery extends InheritedWidget {
);
}
/// Provides a [MediaQuery] which is built and updated using the latest
/// [WidgetsBinding.window] values.
///
/// The [MediaQuery] is wrapped in a separate widget to ensure that only it
/// and its dependents are updated when `window` changes, instead of
/// rebuilding the whole widget tree.
///
/// This should be inserted into the widget tree when the [MediaQuery] view
/// padding is consumed by a widget in such a way that the view padding is no
/// longer exposed to the widget's descendants or siblings.
///
/// The [child] argument is required and must not be null.
static
Widget
fromWindow
({
Key
?
key
,
required
Widget
child
,
})
{
return
_MediaQueryFromWindow
(
key:
key
,
child:
child
,
);
}
/// Contains information about the current media.
///
/// For example, the [MediaQueryData.size] property contains the width and
...
...
@@ -922,3 +945,100 @@ enum NavigationMode {
/// focus (although they remain disabled) when traversed.
directional
,
}
/// Provides a [MediaQuery] which is built and updated using the latest
/// [WidgetsBinding.window] values.
///
/// Receives `window` updates by listening to [WidgetsBinding].
///
/// The standalone widget ensures that it rebuilds **only** [MediaQuery] and
/// its dependents when `window` changes, instead of rebuilding the entire
/// widget tree.
///
/// It is used by [WidgetsApp] if no other [MediaQuery] is available above it.
///
/// See also:
///
/// * [MediaQuery], which establishes a subtree in which media queries resolve
/// to a [MediaQueryData].
class
_MediaQueryFromWindow
extends
StatefulWidget
{
/// Creates a [_MediaQueryFromWindow] that provides a [MediaQuery] to its
/// descendants using the `window` to keep [MediaQueryData] up to date.
///
/// The [child] must not be null.
const
_MediaQueryFromWindow
({
Key
?
key
,
required
this
.
child
,
})
:
super
(
key:
key
);
/// {@macro flutter.widgets.ProxyWidget.child}
final
Widget
child
;
@override
State
<
_MediaQueryFromWindow
>
createState
()
=>
_MediaQueryFromWindowState
();
}
class
_MediaQueryFromWindowState
extends
State
<
_MediaQueryFromWindow
>
with
WidgetsBindingObserver
{
@override
void
initState
()
{
super
.
initState
();
WidgetsBinding
.
instance
!.
addObserver
(
this
);
}
// ACCESSIBILITY
@override
void
didChangeAccessibilityFeatures
()
{
setState
(()
{
// The properties of window have changed. We use them in our build
// function, so we need setState(), but we don't cache anything locally.
});
}
// METRICS
@override
void
didChangeMetrics
()
{
setState
(()
{
// The properties of window have changed. We use them in our build
// function, so we need setState(), but we don't cache anything locally.
});
}
@override
void
didChangeTextScaleFactor
()
{
setState
(()
{
// The textScaleFactor property of window has changed. We reference
// window in our build function, so we need to call setState(), but
// we don't need to cache anything locally.
});
}
// RENDERING
@override
void
didChangePlatformBrightness
()
{
setState
(()
{
// The platformBrightness property of window has changed. We reference
// window in our build function, so we need to call setState(), but
// we don't need to cache anything locally.
});
}
@override
Widget
build
(
BuildContext
context
)
{
MediaQueryData
data
=
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
!.
window
);
if
(!
kReleaseMode
)
{
data
=
data
.
copyWith
(
platformBrightness:
debugBrightnessOverride
);
}
return
MediaQuery
(
data:
data
,
child:
widget
.
child
,
);
}
@override
void
dispose
()
{
WidgetsBinding
.
instance
!.
removeObserver
(
this
);
super
.
dispose
();
}
}
packages/flutter/test/cupertino/app_test.dart
View file @
ea1182ef
...
...
@@ -208,6 +208,26 @@ void main() {
expect
(
scrollBehavior
.
runtimeType
,
MockScrollBehavior
);
expect
(
scrollBehavior
.
getScrollPhysics
(
capturedContext
).
runtimeType
,
NeverScrollableScrollPhysics
);
});
testWidgets
(
'When `useInheritedMediaQuery` is true an existing MediaQuery is used if one is available'
,
(
WidgetTester
tester
)
async
{
late
BuildContext
capturedContext
;
final
UniqueKey
uniqueKey
=
UniqueKey
();
await
tester
.
pumpWidget
(
MediaQuery
(
key:
uniqueKey
,
data:
const
MediaQueryData
(),
child:
CupertinoApp
(
useInheritedMediaQuery:
true
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
capturedContext
=
context
;
return
const
Placeholder
();
},
color:
const
Color
(
0xFF123456
),
),
),
);
expect
(
capturedContext
.
dependOnInheritedWidgetOfExactType
<
MediaQuery
>()?.
key
,
uniqueKey
);
});
}
class
MockScrollBehavior
extends
ScrollBehavior
{
...
...
packages/flutter/test/material/app_test.dart
View file @
ea1182ef
...
...
@@ -1069,6 +1069,26 @@ void main() {
expect
(
scrollBehavior
.
runtimeType
,
MockScrollBehavior
);
expect
(
scrollBehavior
.
getScrollPhysics
(
capturedContext
).
runtimeType
,
NeverScrollableScrollPhysics
);
});
testWidgets
(
'When `useInheritedMediaQuery` is true an existing MediaQuery is used if one is available'
,
(
WidgetTester
tester
)
async
{
late
BuildContext
capturedContext
;
final
UniqueKey
uniqueKey
=
UniqueKey
();
await
tester
.
pumpWidget
(
MediaQuery
(
key:
uniqueKey
,
data:
const
MediaQueryData
(),
child:
MaterialApp
(
useInheritedMediaQuery:
true
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
capturedContext
=
context
;
return
const
Placeholder
();
},
color:
const
Color
(
0xFF123456
),
),
),
);
expect
(
capturedContext
.
dependOnInheritedWidgetOfExactType
<
MediaQuery
>()?.
key
,
uniqueKey
);
});
}
class
MockScrollBehavior
extends
ScrollBehavior
{
...
...
packages/flutter/test/widgets/app_test.dart
View file @
ea1182ef
...
...
@@ -455,6 +455,56 @@ void main() {
const
Locale
(
'zh'
),
);
});
testWidgets
(
'WidgetsApp creates a MediaQuery if `useInheritedMediaQuery` is set to false'
,
(
WidgetTester
tester
)
async
{
late
BuildContext
capturedContext
;
await
tester
.
pumpWidget
(
WidgetsApp
(
useInheritedMediaQuery:
false
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
capturedContext
=
context
;
return
const
Placeholder
();
},
color:
const
Color
(
0xFF123456
),
),
);
expect
(
MediaQuery
.
of
(
capturedContext
),
isNotNull
);
});
testWidgets
(
'WidgetsApp does not create MediaQuery if `useInheritedMediaQuery` is set to true and one is available'
,
(
WidgetTester
tester
)
async
{
late
BuildContext
capturedContext
;
final
UniqueKey
uniqueKey
=
UniqueKey
();
await
tester
.
pumpWidget
(
MediaQuery
(
key:
uniqueKey
,
data:
const
MediaQueryData
(),
child:
WidgetsApp
(
useInheritedMediaQuery:
true
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
capturedContext
=
context
;
return
const
Placeholder
();
},
color:
const
Color
(
0xFF123456
),
),
),
);
expect
(
capturedContext
.
dependOnInheritedWidgetOfExactType
<
MediaQuery
>()?.
key
,
uniqueKey
);
});
testWidgets
(
'WidgetsApp does create a MediaQuery if `useInheritedMediaQuery` is set to true and none is available'
,
(
WidgetTester
tester
)
async
{
late
BuildContext
capturedContext
;
await
tester
.
pumpWidget
(
WidgetsApp
(
useInheritedMediaQuery:
true
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
capturedContext
=
context
;
return
const
Placeholder
();
},
color:
const
Color
(
0xFF123456
),
),
);
expect
(
MediaQuery
.
of
(
capturedContext
),
isNotNull
);
});
}
typedef
SimpleRouterDelegateBuilder
=
Widget
Function
(
BuildContext
,
RouteInformation
);
...
...
packages/flutter/test/widgets/media_query_test.dart
View file @
ea1182ef
...
...
@@ -627,4 +627,49 @@ void main() {
expect
(
outsideBoldTextOverride
,
false
);
expect
(
insideBoldTextOverride
,
true
);
});
testWidgets
(
'MediaQuery.fromWindow creates a MediaQuery'
,
(
WidgetTester
tester
)
async
{
bool
hasMediaQueryAsParentOutside
=
false
;
bool
hasMediaQueryAsParentInside
=
false
;
await
tester
.
pumpWidget
(
Builder
(
builder:
(
BuildContext
context
)
{
hasMediaQueryAsParentOutside
=
context
.
findAncestorWidgetOfExactType
<
MediaQuery
>()
!=
null
;
return
MediaQuery
.
fromWindow
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
hasMediaQueryAsParentInside
=
context
.
findAncestorWidgetOfExactType
<
MediaQuery
>()
!=
null
;
return
const
SizedBox
();
},
),
);
},
),
);
expect
(
hasMediaQueryAsParentOutside
,
false
);
expect
(
hasMediaQueryAsParentInside
,
true
);
});
testWidgets
(
'MediaQueryData.fromWindow is created using window values'
,
(
WidgetTester
tester
)
async
{
final
MediaQueryData
windowData
=
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
!.
window
);
late
MediaQueryData
fromWindowData
;
await
tester
.
pumpWidget
(
MediaQuery
.
fromWindow
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
fromWindowData
=
MediaQuery
.
of
(
context
);
return
const
SizedBox
();
},
),
),
);
expect
(
windowData
,
equals
(
fromWindowData
));
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment