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
4b7a1912
Commit
4b7a1912
authored
May 13, 2017
by
Adam Barth
Committed by
GitHub
May 13, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add NavigatorState.pushAndRemoveUntil (#10026)
Fixes #9989
parent
db84df23
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
100 additions
and
2 deletions
+100
-2
navigator.dart
packages/flutter/lib/src/widgets/navigator.dart
+60
-0
navigator_replacement_test.dart
...ages/flutter/test/widgets/navigator_replacement_test.dart
+40
-2
No files found.
packages/flutter/lib/src/widgets/navigator.dart
View file @
4b7a1912
...
...
@@ -968,6 +968,66 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin {
assert
(()
{
_debugLocked
=
false
;
return
true
;
});
}
/// Push the given route and then remove all the previous routes until the
/// `predicate` returns true.
///
/// The predicate may be applied to the same route more than once if
/// [Route.willHandlePopInternally] is true.
///
/// To remove routes until a route with a certain name, use the
/// [RoutePredicate] returned from [ModalRoute.withName].
///
/// To remove all the routes before the pushed route, use a [RoutePredicate]
/// that always returns false.
Future
<
dynamic
>
pushAndRemoveUntil
(
Route
<
dynamic
>
newRoute
,
RoutePredicate
predicate
)
{
assert
(!
_debugLocked
);
assert
(()
{
_debugLocked
=
true
;
return
true
;
});
final
List
<
Route
<
dynamic
>>
removedRoutes
=
<
Route
<
dynamic
>>[];
while
(
_history
.
isNotEmpty
&&
!
predicate
(
_history
.
last
))
{
final
Route
<
dynamic
>
removedRoute
=
_history
.
removeLast
();
assert
(
removedRoute
!=
null
&&
removedRoute
.
_navigator
==
this
);
assert
(
removedRoute
.
overlayEntries
.
isNotEmpty
);
removedRoutes
.
add
(
removedRoute
);
}
assert
(
newRoute
.
_navigator
==
null
);
assert
(
newRoute
.
overlayEntries
.
isEmpty
);
setState
(()
{
final
Route
<
dynamic
>
oldRoute
=
_history
.
isNotEmpty
?
_history
.
last
:
null
;
newRoute
.
_navigator
=
this
;
newRoute
.
install
(
_currentOverlayEntry
);
_history
.
add
(
newRoute
);
newRoute
.
didPush
().
whenCompleteOrCancel
(()
{
if
(
mounted
)
{
for
(
Route
<
dynamic
>
route
in
removedRoutes
)
route
.
dispose
();
}
});
newRoute
.
didChangeNext
(
null
);
if
(
oldRoute
!=
null
)
oldRoute
.
didChangeNext
(
newRoute
);
for
(
NavigatorObserver
observer
in
widget
.
observers
)
observer
.
didPush
(
newRoute
,
oldRoute
);
});
assert
(()
{
_debugLocked
=
false
;
return
true
;
});
_cancelActivePointers
();
return
newRoute
.
popped
;
}
/// Push the route with the given name and then remove all the previous routes
/// until the `predicate` returns true.
///
/// The predicate may be applied to the same route more than once if
/// [Route.willHandlePopInternally] is true.
///
/// To remove routes until a route with a certain name, use the
/// [RoutePredicate] returned from [ModalRoute.withName].
///
/// To remove all the routes before the pushed route, use a [RoutePredicate]
/// that always returns false.
Future
<
dynamic
>
pushNamedAndRemoveUntil
(
String
routeName
,
RoutePredicate
predicate
)
{
return
pushAndRemoveUntil
(
_routeNamed
(
routeName
),
predicate
);
}
/// Tries to pop the current route, first giving the active route the chance
/// to veto the operation using [Route.willPop]. This method is typically
/// called instead of [pop] when the user uses a back button. For example on
...
...
packages/flutter/test/widgets/navigator_replacement_test.dart
View file @
4b7a1912
...
...
@@ -6,8 +6,7 @@ import 'package:flutter_test/flutter_test.dart';
import
'package:flutter/material.dart'
;
void
main
(
)
{
testWidgets
(
'Back during pushReplacement'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Back during pushReplacement'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
const
Material
(
child:
const
Text
(
"home"
)),
routes:
<
String
,
WidgetBuilder
>
{
...
...
@@ -39,4 +38,43 @@ void main() {
expect
(
find
.
text
(
'b'
),
findsNothing
);
expect
(
find
.
text
(
'home'
),
findsOneWidget
);
});
testWidgets
(
'pushAndRemoveUntil'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
const
Material
(
child:
const
Text
(
"home"
)),
routes:
<
String
,
WidgetBuilder
>
{
'/a'
:
(
BuildContext
context
)
=>
const
Material
(
child:
const
Text
(
"a"
)),
'/b'
:
(
BuildContext
context
)
=>
const
Material
(
child:
const
Text
(
"b"
)),
},
));
final
NavigatorState
navigator
=
tester
.
state
(
find
.
byType
(
Navigator
));
navigator
.
pushNamed
(
'/a'
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'home'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'a'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'b'
,
skipOffstage:
false
),
findsNothing
);
navigator
.
pushNamedAndRemoveUntil
(
'/b'
,
(
Route
<
dynamic
>
route
)
=>
false
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'home'
,
skipOffstage:
false
),
findsNothing
);
expect
(
find
.
text
(
'a'
,
skipOffstage:
false
),
findsNothing
);
expect
(
find
.
text
(
'b'
,
skipOffstage:
false
),
findsOneWidget
);
navigator
.
pushNamed
(
'/'
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'home'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'a'
,
skipOffstage:
false
),
findsNothing
);
expect
(
find
.
text
(
'b'
,
skipOffstage:
false
),
findsOneWidget
);
navigator
.
pushNamedAndRemoveUntil
(
'/a'
,
ModalRoute
.
withName
(
'/b'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'home'
,
skipOffstage:
false
),
findsNothing
);
expect
(
find
.
text
(
'a'
,
skipOffstage:
false
),
findsOneWidget
);
expect
(
find
.
text
(
'b'
,
skipOffstage:
false
),
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