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
07a09c4b
Unverified
Commit
07a09c4b
authored
Oct 31, 2019
by
Michael Goderbauer
Committed by
GitHub
Oct 31, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Mark routes as opaque when added without animation (#43756)
parent
8e0799a6
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
179 additions
and
21 deletions
+179
-21
overlay.dart
packages/flutter/lib/src/widgets/overlay.dart
+1
-2
routes.dart
packages/flutter/lib/src/widgets/routes.dart
+11
-2
app_test.dart
packages/flutter/test/material/app_test.dart
+12
-12
heroes_test.dart
packages/flutter/test/widgets/heroes_test.dart
+3
-1
navigator_test.dart
packages/flutter/test/widgets/navigator_test.dart
+111
-4
overlay_test.dart
packages/flutter/test/widgets/overlay_test.dart
+41
-0
No files found.
packages/flutter/lib/src/widgets/overlay.dart
View file @
07a09c4b
...
...
@@ -86,8 +86,7 @@ class OverlayEntry {
if
(
_opaque
==
value
)
return
;
_opaque
=
value
;
assert
(
_overlay
!=
null
);
_overlay
.
_didChangeEntryOpacity
();
_overlay
?.
_didChangeEntryOpacity
();
}
/// Whether this entry must be included in the tree even if there is a fully
...
...
packages/flutter/lib/src/widgets/routes.dart
View file @
07a09c4b
...
...
@@ -184,7 +184,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
TickerFuture
didPush
()
{
assert
(
_controller
!=
null
,
'
$runtimeType
.didPush called before calling install() or after calling dispose().'
);
assert
(!
_transitionCompleter
.
isCompleted
,
'Cannot reuse a
$runtimeType
after disposing it.'
);
_
animation
.
addStatusListener
(
_handleStatusChanged
);
_
didPushOrReplace
(
);
super
.
didPush
();
return
_controller
.
forward
();
}
...
...
@@ -195,10 +195,19 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
assert
(!
_transitionCompleter
.
isCompleted
,
'Cannot reuse a
$runtimeType
after disposing it.'
);
if
(
oldRoute
is
TransitionRoute
)
_controller
.
value
=
oldRoute
.
_controller
.
value
;
_
animation
.
addStatusListener
(
_handleStatusChanged
);
_
didPushOrReplace
(
);
super
.
didReplace
(
oldRoute
);
}
void
_didPushOrReplace
()
{
_animation
.
addStatusListener
(
_handleStatusChanged
);
// If the animation is already completed, _handleStatusChanged will not get
// a chance to set opaqueness of OverlayEntry.
if
(
_animation
.
isCompleted
&&
overlayEntries
.
isNotEmpty
)
{
overlayEntries
.
first
.
opaque
=
opaque
;
}
}
@override
bool
didPop
(
T
result
)
{
assert
(
_controller
!=
null
,
'
$runtimeType
.didPop called before calling install() or after calling dispose().'
);
...
...
packages/flutter/test/material/app_test.dart
View file @
07a09c4b
...
...
@@ -241,10 +241,10 @@ void main() {
),
);
expect
(
find
.
text
(
'route "/"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/"'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/a"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/a/b"'
),
findsNothing
);
expect
(
find
.
text
(
'route "/b"'
),
findsNothing
);
expect
(
find
.
text
(
'route "/a/b"'
,
skipOffstage:
false
),
findsNothing
);
expect
(
find
.
text
(
'route "/b"'
,
skipOffstage:
false
),
findsNothing
);
});
testWidgets
(
'Return value from pop is correct'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -301,10 +301,10 @@ void main() {
routes:
routes
,
),
);
expect
(
find
.
text
(
'route "/"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/a"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/"'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/a"'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/a/b"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/b"'
),
findsNothing
);
expect
(
find
.
text
(
'route "/b"'
,
skipOffstage:
false
),
findsNothing
);
});
testWidgets
(
'Initial route with missing step'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -343,9 +343,9 @@ void main() {
routes:
routes
,
),
);
expect
(
find
.
text
(
'route "/"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/"'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/a"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/b"'
),
findsNothing
);
expect
(
find
.
text
(
'route "/b"'
,
skipOffstage:
false
),
findsNothing
);
// changing initialRoute has no effect
await
tester
.
pumpWidget
(
...
...
@@ -354,15 +354,15 @@ void main() {
routes:
routes
,
),
);
expect
(
find
.
text
(
'route "/"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/"'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/a"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/b"'
),
findsNothing
);
expect
(
find
.
text
(
'route "/b"'
,
skipOffstage:
false
),
findsNothing
);
// removing it has no effect
await
tester
.
pumpWidget
(
MaterialApp
(
routes:
routes
));
expect
(
find
.
text
(
'route "/"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/"'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/a"'
),
findsOneWidget
);
expect
(
find
.
text
(
'route "/b"'
),
findsNothing
);
expect
(
find
.
text
(
'route "/b"'
,
skipOffstage:
false
),
findsNothing
);
});
testWidgets
(
'onGenerateRoute / onUnknownRoute'
,
(
WidgetTester
tester
)
async
{
...
...
packages/flutter/test/widgets/heroes_test.dart
View file @
07a09c4b
...
...
@@ -1754,7 +1754,9 @@ Future<void> main() async {
routes:
routes
,
initialRoute:
'/two'
,
));
expect
(
find
.
text
(
'two'
),
findsOneWidget
);
expect
(
tester
.
takeException
(),
isNull
);
expect
(
find
.
text
(
'two'
),
findsNothing
);
expect
(
find
.
text
(
'three'
),
findsOneWidget
);
});
testWidgets
(
'Can push/pop on outer Navigator if nested Navigator contains Heroes'
,
(
WidgetTester
tester
)
async
{
...
...
packages/flutter/test/widgets/navigator_test.dart
View file @
07a09c4b
...
...
@@ -994,15 +994,15 @@ void main() {
);
// The initial route /A/B/C should've been pushed successfully.
expect
(
find
.
byKey
(
keyRoot
),
findsOneWidget
);
expect
(
find
.
byKey
(
keyA
),
findsOneWidget
);
expect
(
find
.
byKey
(
keyRoot
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
byKey
(
keyA
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
byKey
(
keyABC
),
findsOneWidget
);
keyNav
.
currentState
.
pop
();
await
tester
.
pumpAndSettle
();
expect
(
find
.
byKey
(
keyRoot
),
findsOneWidget
);
expect
(
find
.
byKey
(
keyRoot
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
byKey
(
keyA
),
findsOneWidget
);
expect
(
find
.
byKey
(
keyABC
),
findsNothing
);
expect
(
find
.
byKey
(
keyABC
,
skipOffstage:
false
),
findsNothing
);
});
testWidgets
(
'The full initial route has to be matched'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -1089,4 +1089,111 @@ void main() {
});
});
testWidgets
(
'OverlayEntry of topmost initial route is marked as opaque'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/38038.
final
Key
root
=
UniqueKey
();
final
Key
intermediate
=
UniqueKey
();
final
GlobalKey
topmost
=
GlobalKey
();
await
tester
.
pumpWidget
(
MaterialApp
(
initialRoute:
'/A/B'
,
routes:
<
String
,
WidgetBuilder
>{
'/'
:
(
BuildContext
context
)
=>
Container
(
key:
root
),
'/A'
:
(
BuildContext
context
)
=>
Container
(
key:
intermediate
),
'/A/B'
:
(
BuildContext
context
)
=>
Container
(
key:
topmost
),
},
),
);
expect
(
ModalRoute
.
of
(
topmost
.
currentContext
).
overlayEntries
.
first
.
opaque
,
isTrue
);
expect
(
find
.
byKey
(
root
),
findsNothing
);
// hidden by opaque Route
expect
(
find
.
byKey
(
intermediate
),
findsNothing
);
// hidden by opaque Route
expect
(
find
.
byKey
(
topmost
),
findsOneWidget
);
});
testWidgets
(
'OverlayEntry of topmost route is set to opaque after Push'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/38038.
final
GlobalKey
<
NavigatorState
>
navigator
=
GlobalKey
<
NavigatorState
>();
await
tester
.
pumpWidget
(
MaterialApp
(
navigatorKey:
navigator
,
initialRoute:
'/'
,
onGenerateRoute:
(
RouteSettings
settings
)
{
return
NoAnimationPageRoute
(
pageBuilder:
(
_
)
=>
Container
(
key:
ValueKey
<
String
>(
settings
.
name
)),
);
},
),
);
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/'
)),
findsOneWidget
);
navigator
.
currentState
.
pushNamed
(
'/A'
);
await
tester
.
pump
();
final
BuildContext
topMostContext
=
tester
.
element
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A'
)));
expect
(
ModalRoute
.
of
(
topMostContext
).
overlayEntries
.
first
.
opaque
,
isTrue
);
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/'
)),
findsNothing
);
// hidden by /A
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A'
)),
findsOneWidget
);
});
testWidgets
(
'OverlayEntry of topmost route is set to opaque after Replace'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/38038.
final
GlobalKey
<
NavigatorState
>
navigator
=
GlobalKey
<
NavigatorState
>();
await
tester
.
pumpWidget
(
MaterialApp
(
navigatorKey:
navigator
,
initialRoute:
'/A/B'
,
onGenerateRoute:
(
RouteSettings
settings
)
{
return
NoAnimationPageRoute
(
pageBuilder:
(
_
)
=>
Container
(
key:
ValueKey
<
String
>(
settings
.
name
)),
);
},
),
);
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/'
)),
findsNothing
);
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A'
)),
findsNothing
);
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A/B'
)),
findsOneWidget
);
final
Route
<
dynamic
>
oldRoute
=
ModalRoute
.
of
(
tester
.
element
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A'
),
skipOffstage:
false
)),
);
final
Route
<
void
>
newRoute
=
NoAnimationPageRoute
(
pageBuilder:
(
_
)
=>
Container
(
key:
const
ValueKey
<
String
>(
'/C'
)),
);
navigator
.
currentState
.
replace
<
void
>(
oldRoute:
oldRoute
,
newRoute:
newRoute
);
await
tester
.
pump
();
expect
(
newRoute
.
overlayEntries
.
first
.
opaque
,
isTrue
);
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/'
)),
findsNothing
);
// hidden by /A/B
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A'
)),
findsNothing
);
// replaced
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/C'
)),
findsNothing
);
// hidden by /A/B
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A/B'
)),
findsOneWidget
);
navigator
.
currentState
.
pop
();
await
tester
.
pumpAndSettle
();
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/'
)),
findsNothing
);
// hidden by /C
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A'
)),
findsNothing
);
// replaced
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/A/B'
)),
findsNothing
);
// popped
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'/C'
)),
findsOneWidget
);
});
}
class
NoAnimationPageRoute
extends
PageRouteBuilder
<
void
>
{
NoAnimationPageRoute
({
WidgetBuilder
pageBuilder
})
:
super
(
pageBuilder:
(
BuildContext
context
,
__
,
___
)
{
return
pageBuilder
(
context
);
});
@override
AnimationController
createAnimationController
()
{
return
super
.
createAnimationController
()..
value
=
1.0
;
}
}
packages/flutter/test/widgets/overlay_test.dart
View file @
07a09c4b
...
...
@@ -657,4 +657,45 @@ void main() {
),
);
});
testWidgets
(
'OverlayEntry.opaque can be changed when OverlayEntry is not part of an Overlay (yet)'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
OverlayState
>
overlayKey
=
GlobalKey
<
OverlayState
>();
final
Key
root
=
UniqueKey
();
final
Key
top
=
UniqueKey
();
final
OverlayEntry
rootEntry
=
OverlayEntry
(
builder:
(
BuildContext
context
)
{
return
Container
(
key:
root
);
},
);
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
Overlay
(
key:
overlayKey
,
initialEntries:
<
OverlayEntry
>[
rootEntry
,
],
),
),
);
expect
(
find
.
byKey
(
root
),
findsOneWidget
);
final
OverlayEntry
newEntry
=
OverlayEntry
(
builder:
(
BuildContext
context
)
{
return
Container
(
key:
top
);
},
);
expect
(
newEntry
.
opaque
,
isFalse
);
newEntry
.
opaque
=
true
;
// Does neither trigger an assert nor throw.
expect
(
newEntry
.
opaque
,
isTrue
);
// The new opaqueness is honored when inserted into an overlay.
overlayKey
.
currentState
.
insert
(
newEntry
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
byKey
(
root
),
findsNothing
);
expect
(
find
.
byKey
(
top
),
findsOneWidget
);
});
}
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