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
e8b87203
Unverified
Commit
e8b87203
authored
Mar 04, 2019
by
Hans Muller
Committed by
GitHub
Mar 04, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Handle Cupertino back gesture interrupted by Navigator push (#28756)
parent
a1aea2e4
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
91 additions
and
20 deletions
+91
-20
route.dart
packages/flutter/lib/src/cupertino/route.dart
+12
-17
routes.dart
packages/flutter/lib/src/widgets/routes.dart
+3
-3
route_test.dart
packages/flutter/test/cupertino/route_test.dart
+76
-0
No files found.
packages/flutter/lib/src/cupertino/route.dart
View file @
e8b87203
...
...
@@ -272,8 +272,8 @@ class CupertinoPageRoute<T> extends PageRoute<T> {
_CupertinoBackGestureController
<
T
>
backController
;
backController
=
_CupertinoBackGestureController
<
T
>(
navigator:
route
.
navigator
,
controller:
route
.
controller
,
route:
route
,
controller:
route
.
controller
,
// protected access
onEnded:
()
{
backController
?.
dispose
();
backController
=
null
;
...
...
@@ -576,22 +576,15 @@ class _CupertinoBackGestureController<T> {
///
/// The [navigator] and [controller] arguments must not be null.
_CupertinoBackGestureController
({
@required
this
.
navigator
,
@required
this
.
route
,
@required
this
.
controller
,
@required
this
.
onEnded
,
})
:
assert
(
navigator
!=
null
),
assert
(
controller
!=
null
),
assert
(
onEnded
!=
null
)
{
navigator
.
didStartUserGesture
();
})
:
assert
(
route
!=
null
),
assert
(
controller
!=
null
),
assert
(
onEnded
!=
null
)
{
route
.
navigator
.
didStartUserGesture
();
}
/// The navigator that this object is controlling.
final
NavigatorState
navigator
;
/// The animation controller that the route uses to drive its transition
/// animation.
final
PageRoute
<
T
>
route
;
final
AnimationController
controller
;
final
VoidCallback
onEnded
;
bool
_animating
=
false
;
...
...
@@ -626,8 +619,10 @@ class _CupertinoBackGestureController<T> {
// The closer the panel is to dismissing, the shorter the animation is.
// We want to cap the animation time, but we want to use a linear curve
// to determine it.
final
int
droppedPageForwardAnimationTime
=
min
(
lerpDouble
(
_kMaxDroppedSwipePageForwardAnimationTime
,
0
,
controller
.
value
).
floor
(),
_kMaxPageBackAnimationTime
);
final
int
droppedPageForwardAnimationTime
=
min
(
lerpDouble
(
_kMaxDroppedSwipePageForwardAnimationTime
,
0
,
controller
.
value
).
floor
(),
_kMaxPageBackAnimationTime
,
);
controller
.
animateTo
(
1.0
,
duration:
Duration
(
milliseconds:
droppedPageForwardAnimationTime
),
curve:
animationCurve
);
}
else
{
final
int
droppedPageBackAnimationTime
=
lerpDouble
(
0
,
_kMaxDroppedSwipePageForwardAnimationTime
,
controller
.
value
).
floor
();
...
...
@@ -652,14 +647,14 @@ class _CupertinoBackGestureController<T> {
}
_animating
=
false
;
if
(
status
==
AnimationStatus
.
dismissed
)
navigator
.
pop
<
T
>(
);
// this will cause the route to get disposed, which will dispose us
route
.
navigator
.
removeRoute
(
route
);
// this will cause the route to get disposed, which will dispose us
onEnded
();
// this will call dispose if popping the route failed to do so
}
void
dispose
()
{
if
(
_animating
)
controller
.
removeStatusListener
(
_handleStatusChanged
);
navigator
.
didStopUserGesture
();
route
.
navigator
?
.
didStopUserGesture
();
}
}
...
...
packages/flutter/lib/src/widgets/routes.dart
View file @
e8b87203
...
...
@@ -151,11 +151,11 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
overlayEntries
.
first
.
opaque
=
false
;
break
;
case
AnimationStatus
.
dismissed
:
// We might still be
the current
route if a subclass is controlling the
// We might still be
an active
route if a subclass is controlling the
// the transition and hits the dismissed status. For example, the iOS
// back gesture drives this animation to the dismissed status before
//
popping the navigator
.
if
(!
is
Current
)
{
//
removing the route and disposing it
.
if
(!
is
Active
)
{
navigator
.
finalizeRoute
(
this
);
assert
(
overlayEntries
.
isEmpty
);
}
...
...
packages/flutter/test/cupertino/route_test.dart
View file @
e8b87203
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
...
...
@@ -253,4 +254,79 @@ void main() {
expect
(
find
.
widgetWithText
(
CupertinoButton
,
'Back'
),
findsOneWidget
);
expect
(
tester
.
getTopLeft
(
find
.
text
(
'Back'
)).
dx
,
8.0
+
34.0
+
6.0
);
});
testWidgets
(
'Back swipe dismiss interrupted by route push'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
scaffoldKey
=
GlobalKey
();
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
platform:
TargetPlatform
.
iOS
),
home:
Scaffold
(
key:
scaffoldKey
,
body:
Center
(
child:
RaisedButton
(
onPressed:
()
{
Navigator
.
push
<
void
>(
scaffoldKey
.
currentContext
,
MaterialPageRoute
<
void
>(
builder:
(
BuildContext
context
)
{
return
const
Scaffold
(
body:
Center
(
child:
Text
(
'route'
)),
);
},
));
},
child:
const
Text
(
'push'
),
),
),
),
),
);
// Check the basic iOS back-swipe dismiss transition. Dragging the pushed
// route halfway across the screen will trigger the iOS dismiss animation
await
tester
.
tap
(
find
.
text
(
'push'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'route'
),
findsOneWidget
);
expect
(
find
.
text
(
'push'
),
findsNothing
);
TestGesture
gesture
=
await
tester
.
startGesture
(
const
Offset
(
5
,
300
));
await
gesture
.
moveBy
(
const
Offset
(
400
,
0
));
await
gesture
.
up
();
await
tester
.
pump
();
expect
(
// The 'route' route has been dragged to the right, halfway across the screen
tester
.
getTopLeft
(
find
.
ancestor
(
of:
find
.
text
(
'route'
),
matching:
find
.
byType
(
Scaffold
))),
const
Offset
(
400
,
0
),
);
expect
(
// The 'push' route is sliding in from the left.
tester
.
getTopLeft
(
find
.
ancestor
(
of:
find
.
text
(
'push'
),
matching:
find
.
byType
(
Scaffold
))).
dx
,
lessThan
(
0
),
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'push'
),
findsOneWidget
);
expect
(
tester
.
getTopLeft
(
find
.
ancestor
(
of:
find
.
text
(
'push'
),
matching:
find
.
byType
(
Scaffold
))),
Offset
.
zero
,
);
expect
(
find
.
text
(
'route'
),
findsNothing
);
// Run the dismiss animation 75%, which exposes the route "push" button,
// and then press the button. MaterialPageTransition duration is 300ms,
// 275 = 300 * 0.75.
await
tester
.
tap
(
find
.
text
(
'push'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'route'
),
findsOneWidget
);
expect
(
find
.
text
(
'push'
),
findsNothing
);
gesture
=
await
tester
.
startGesture
(
const
Offset
(
5
,
300
));
await
gesture
.
moveBy
(
const
Offset
(
400
,
0
));
// drag halfway
await
gesture
.
up
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
275
));
// partially dismiss "route"
expect
(
find
.
text
(
'route'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
text
(
'push'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'route'
),
findsOneWidget
);
expect
(
find
.
text
(
'push'
),
findsNothing
);
});
}
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