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
6c9071d3
Unverified
Commit
6c9071d3
authored
Mar 28, 2020
by
Pieter van Loon
Committed by
GitHub
Mar 28, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added parallax effect for cupertino fullscreenDialog (#50180)
parent
94500073
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
220 additions
and
12 deletions
+220
-12
route.dart
packages/flutter/lib/src/cupertino/route.dart
+42
-12
route_test.dart
packages/flutter/test/cupertino/route_test.dart
+178
-0
No files found.
packages/flutter/lib/src/cupertino/route.dart
View file @
6c9071d3
...
@@ -300,21 +300,24 @@ class CupertinoPageRoute<T> extends PageRoute<T> {
...
@@ -300,21 +300,24 @@ class CupertinoPageRoute<T> extends PageRoute<T> {
Animation
<
double
>
secondaryAnimation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
,
Widget
child
,
)
{
)
{
// Check if the route has an animation that's currently participating
// in a back swipe gesture.
//
// In the middle of a back gesture drag, let the transition be linear to
// match finger motions.
final
bool
linearTransition
=
isPopGestureInProgress
(
route
);
if
(
route
.
fullscreenDialog
)
{
if
(
route
.
fullscreenDialog
)
{
return
CupertinoFullscreenDialogTransition
(
return
CupertinoFullscreenDialogTransition
(
animation:
animation
,
primaryRouteAnimation:
animation
,
secondaryRouteAnimation:
secondaryAnimation
,
child:
child
,
child:
child
,
linearTransition:
linearTransition
,
);
);
}
else
{
}
else
{
return
CupertinoPageTransition
(
return
CupertinoPageTransition
(
primaryRouteAnimation:
animation
,
primaryRouteAnimation:
animation
,
secondaryRouteAnimation:
secondaryAnimation
,
secondaryRouteAnimation:
secondaryAnimation
,
// Check if the route has an animation that's currently participating
linearTransition:
linearTransition
,
// in a back swipe gesture.
//
// In the middle of a back gesture drag, let the transition be linear to
// match finger motions.
linearTransition:
isPopGestureInProgress
(
route
),
child:
_CupertinoBackGestureDetector
<
T
>(
child:
_CupertinoBackGestureDetector
<
T
>(
enabledCallback:
()
=>
_isPopGestureEnabled
<
T
>(
route
),
enabledCallback:
()
=>
_isPopGestureEnabled
<
T
>(
route
),
onStartPopGesture:
()
=>
_startPopGesture
<
T
>(
route
),
onStartPopGesture:
()
=>
_startPopGesture
<
T
>(
route
),
...
@@ -344,7 +347,7 @@ class CupertinoPageTransition extends StatelessWidget {
...
@@ -344,7 +347,7 @@ class CupertinoPageTransition extends StatelessWidget {
/// when this screen is being pushed.
/// when this screen is being pushed.
/// * `secondaryRouteAnimation` is a linear route animation from 0.0 to 1.0
/// * `secondaryRouteAnimation` is a linear route animation from 0.0 to 1.0
/// when another screen is being pushed on top of this one.
/// when another screen is being pushed on top of this one.
/// * `linearTransition` is whether to perform
primary transition
linearly.
/// * `linearTransition` is whether to perform
the transitions
linearly.
/// Used to precisely track back gesture drags.
/// Used to precisely track back gesture drags.
CupertinoPageTransition
({
CupertinoPageTransition
({
Key
key
,
Key
key
,
...
@@ -422,29 +425,56 @@ class CupertinoPageTransition extends StatelessWidget {
...
@@ -422,29 +425,56 @@ class CupertinoPageTransition extends StatelessWidget {
/// screen from the bottom.
/// screen from the bottom.
class
CupertinoFullscreenDialogTransition
extends
StatelessWidget
{
class
CupertinoFullscreenDialogTransition
extends
StatelessWidget
{
/// Creates an iOS-style transition used for summoning fullscreen dialogs.
/// Creates an iOS-style transition used for summoning fullscreen dialogs.
///
/// * `primaryRouteAnimation` is a linear route animation from 0.0 to 1.0
/// when this screen is being pushed.
/// * `secondaryRouteAnimation` is a linear route animation from 0.0 to 1.0
/// when another screen is being pushed on top of this one.
/// * `linearTransition` is whether to perform the secondary transition linearly.
/// Used to precisely track back gesture drags.
CupertinoFullscreenDialogTransition
({
CupertinoFullscreenDialogTransition
({
Key
key
,
Key
key
,
@required
Animation
<
double
>
animation
,
@required
Animation
<
double
>
primaryRouteAnimation
,
@required
Animation
<
double
>
secondaryRouteAnimation
,
@required
this
.
child
,
@required
this
.
child
,
@required
bool
linearTransition
,
})
:
_positionAnimation
=
CurvedAnimation
(
})
:
_positionAnimation
=
CurvedAnimation
(
parent:
a
nimation
,
parent:
primaryRouteA
nimation
,
curve:
Curves
.
linearToEaseOut
,
curve:
Curves
.
linearToEaseOut
,
// The curve must be flipped so that the reverse animation doesn't play
// The curve must be flipped so that the reverse animation doesn't play
// an ease-in curve, which iOS does not use.
// an ease-in curve, which iOS does not use.
reverseCurve:
Curves
.
linearToEaseOut
.
flipped
,
reverseCurve:
Curves
.
linearToEaseOut
.
flipped
,
).
drive
(
_kBottomUpTween
),
).
drive
(
_kBottomUpTween
),
_secondaryPositionAnimation
=
(
linearTransition
?
secondaryRouteAnimation
:
CurvedAnimation
(
parent:
secondaryRouteAnimation
,
curve:
Curves
.
linearToEaseOut
,
reverseCurve:
Curves
.
easeInToLinear
,
)
).
drive
(
_kMiddleLeftTween
),
super
(
key:
key
);
super
(
key:
key
);
final
Animation
<
Offset
>
_positionAnimation
;
final
Animation
<
Offset
>
_positionAnimation
;
// When this page is becoming covered by another page.
final
Animation
<
Offset
>
_secondaryPositionAnimation
;
/// The widget below this widget in the tree.
/// The widget below this widget in the tree.
final
Widget
child
;
final
Widget
child
;
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
assert
(
debugCheckHasDirectionality
(
context
));
final
TextDirection
textDirection
=
Directionality
.
of
(
context
);
return
SlideTransition
(
return
SlideTransition
(
position:
_positionAnimation
,
position:
_secondaryPositionAnimation
,
child:
child
,
textDirection:
textDirection
,
transformHitTests:
false
,
child:
SlideTransition
(
position:
_positionAnimation
,
child:
child
,
),
);
);
}
}
}
}
...
...
packages/flutter/test/cupertino/route_test.dart
View file @
6c9071d3
...
@@ -502,6 +502,184 @@ void main() {
...
@@ -502,6 +502,184 @@ void main() {
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dy
,
closeTo
(
600.0
,
0.1
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dy
,
closeTo
(
600.0
,
0.1
));
});
});
Future
<
void
>
testParallax
(
WidgetTester
tester
,
{
@required
bool
fromFullscreenDialog
})
async
{
await
tester
.
pumpWidget
(
CupertinoApp
(
onGenerateRoute:
(
RouteSettings
settings
)
=>
CupertinoPageRoute
<
void
>(
fullscreenDialog:
fromFullscreenDialog
,
settings:
settings
,
builder:
(
BuildContext
context
)
{
return
Column
(
children:
<
Widget
>[
const
Placeholder
(),
CupertinoButton
(
child:
const
Text
(
'Button'
),
onPressed:
()
{
Navigator
.
push
<
void
>(
context
,
CupertinoPageRoute
<
void
>(
builder:
(
BuildContext
context
)
{
return
CupertinoButton
(
child:
const
Text
(
'Close'
),
onPressed:
()
{
Navigator
.
pop
<
void
>(
context
);
},
);
},
));
},
),
],
);
}
),
),
);
// Enter animation.
await
tester
.
tap
(
find
.
text
(
'Button'
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(
0.0
,
0.1
));
await
tester
.
pump
();
// We use a higher number of intervals since the animation has to scale the
// entire screen.
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
70.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
137.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
192.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
227.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
246.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
255.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
260.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
264.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
266.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
267.0
,
1.0
));
// Exit animation
await
tester
.
tap
(
find
.
text
(
'Button'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
198.0
,
1.0
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
360
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(-
0.0
,
1.0
));
}
testWidgets
(
'CupertinoPageRoute has parallax when non fullscreenDialog route is pushed on top'
,
(
WidgetTester
tester
)
async
{
await
testParallax
(
tester
,
fromFullscreenDialog:
false
);
});
testWidgets
(
'FullscreenDialog CupertinoPageRoute has parallax when non fullscreenDialog route is pushed on top'
,
(
WidgetTester
tester
)
async
{
await
testParallax
(
tester
,
fromFullscreenDialog:
true
);
});
Future
<
void
>
testNoParallax
(
WidgetTester
tester
,
{
@required
bool
fromFullscreenDialog
})
async
{
await
tester
.
pumpWidget
(
CupertinoApp
(
onGenerateRoute:
(
RouteSettings
settings
)
=>
CupertinoPageRoute
<
void
>(
fullscreenDialog:
fromFullscreenDialog
,
builder:
(
BuildContext
context
)
{
return
Column
(
children:
<
Widget
>[
const
Placeholder
(),
CupertinoButton
(
child:
const
Text
(
'Button'
),
onPressed:
()
{
Navigator
.
push
<
void
>(
context
,
CupertinoPageRoute
<
void
>(
fullscreenDialog:
true
,
builder:
(
BuildContext
context
)
{
return
CupertinoButton
(
child:
const
Text
(
'Close'
),
onPressed:
()
{
Navigator
.
pop
<
void
>(
context
);
},
);
},
));
},
),
],
);
}
),
),
);
// Enter animation.
await
tester
.
tap
(
find
.
text
(
'Button'
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
closeTo
(
0.0
,
0.1
));
await
tester
.
pump
();
// We use a higher number of intervals since the animation has to scale the
// entire screen.
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
// Exit animation
await
tester
.
tap
(
find
.
text
(
'Button'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
40
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
360
));
expect
(
tester
.
getTopLeft
(
find
.
byType
(
Placeholder
)).
dx
,
0.0
);
}
testWidgets
(
'CupertinoPageRoute has no parallax when fullscreenDialog route is pushed on top'
,
(
WidgetTester
tester
)
async
{
await
testNoParallax
(
tester
,
fromFullscreenDialog:
false
);
});
testWidgets
(
'FullscreenDialog CupertinoPageRoute has no parallax when fullscreenDialog route is pushed on top'
,
(
WidgetTester
tester
)
async
{
await
testNoParallax
(
tester
,
fromFullscreenDialog:
true
);
});
testWidgets
(
'Animated push/pop is not linear'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Animated push/pop is not linear'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
const
CupertinoApp
(
const
CupertinoApp
(
...
...
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