Commit 20e214fa authored by Hans Muller's avatar Hans Muller Committed by GitHub

Document the buildTransitions() method (#9182)

parent 896ffcdf
...@@ -29,8 +29,8 @@ class ShrinePageRoute<T> extends MaterialPageRoute<T> { ...@@ -29,8 +29,8 @@ class ShrinePageRoute<T> extends MaterialPageRoute<T> {
}) : super(builder: builder, settings: settings); }) : super(builder: builder, settings: settings);
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return buildShrine(context, super.buildPage(context, animation, forwardAnimation)); return buildShrine(context, super.buildPage(context, animation, secondaryAnimation));
} }
} }
......
...@@ -231,7 +231,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> { ...@@ -231,7 +231,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
} }
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
Widget bottomSheet = new _ModalBottomSheet<T>(route: this); Widget bottomSheet = new _ModalBottomSheet<T>(route: this);
if (theme != null) if (theme != null)
bottomSheet = new Theme(data: theme, child: bottomSheet); bottomSheet = new Theme(data: theme, child: bottomSheet);
......
...@@ -337,12 +337,12 @@ class _DialogRoute<T> extends PopupRoute<T> { ...@@ -337,12 +337,12 @@ class _DialogRoute<T> extends PopupRoute<T> {
Color get barrierColor => Colors.black54; Color get barrierColor => Colors.black54;
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return theme != null ? new Theme(data: theme, child: child) : child; return theme != null ? new Theme(data: theme, child: child) : child;
} }
@override @override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child) { Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return new FadeTransition( return new FadeTransition(
opacity: new CurvedAnimation( opacity: new CurvedAnimation(
parent: animation, parent: animation,
......
...@@ -313,7 +313,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> { ...@@ -313,7 +313,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
Color get barrierColor => null; Color get barrierColor => null;
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
Widget menu = new _DropdownMenu<T>(route: this); Widget menu = new _DropdownMenu<T>(route: this);
if (theme != null) if (theme != null)
menu = new Theme(data: theme, child: menu); menu = new Theme(data: theme, child: menu);
......
...@@ -149,7 +149,7 @@ class MaterialPageRoute<T> extends PageRoute<T> { ...@@ -149,7 +149,7 @@ class MaterialPageRoute<T> extends PageRoute<T> {
} }
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
final Widget result = builder(context); final Widget result = builder(context);
assert(() { assert(() {
if (result == null) { if (result == null) {
...@@ -164,7 +164,7 @@ class MaterialPageRoute<T> extends PageRoute<T> { ...@@ -164,7 +164,7 @@ class MaterialPageRoute<T> extends PageRoute<T> {
} }
@override @override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child) { Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
if (Theme.of(context).platform == TargetPlatform.iOS) { if (Theme.of(context).platform == TargetPlatform.iOS) {
if (fullscreenDialog) if (fullscreenDialog)
return new CupertinoFullscreenDialogTransition( return new CupertinoFullscreenDialogTransition(
...@@ -174,7 +174,7 @@ class MaterialPageRoute<T> extends PageRoute<T> { ...@@ -174,7 +174,7 @@ class MaterialPageRoute<T> extends PageRoute<T> {
else else
return new CupertinoPageTransition( return new CupertinoPageTransition(
incomingRouteAnimation: animation, incomingRouteAnimation: animation,
outgoingRouteAnimation: forwardAnimation, outgoingRouteAnimation: secondaryAnimation,
child: child, child: child,
// In the middle of a back gesture drag, let the transition be linear to match finger // In the middle of a back gesture drag, let the transition be linear to match finger
// motions. // motions.
......
...@@ -402,7 +402,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> { ...@@ -402,7 +402,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
Color get barrierColor => null; Color get barrierColor => null;
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
double selectedItemOffset; double selectedItemOffset;
if (initialValue != null) { if (initialValue != null) {
selectedItemOffset = 0.0; selectedItemOffset = 0.0;
......
...@@ -46,15 +46,15 @@ abstract class PageRoute<T> extends ModalRoute<T> { ...@@ -46,15 +46,15 @@ abstract class PageRoute<T> extends ModalRoute<T> {
/// primary contents. /// primary contents.
/// ///
/// See [ModalRoute.buildPage] for complete definition of the parameters. /// See [ModalRoute.buildPage] for complete definition of the parameters.
typedef Widget RoutePageBuilder(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation); typedef Widget RoutePageBuilder(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation);
/// Signature for the [PageRouteBuilder] function that builds the route's /// Signature for the [PageRouteBuilder] function that builds the route's
/// transitions. /// transitions.
/// ///
/// See [ModalRoute.buildTransitions] for complete definition of the parameters. /// See [ModalRoute.buildTransitions] for complete definition of the parameters.
typedef Widget RouteTransitionsBuilder(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child); typedef Widget RouteTransitionsBuilder(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child);
Widget _defaultTransitionsBuilder(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child) { Widget _defaultTransitionsBuilder(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return child; return child;
} }
...@@ -110,13 +110,13 @@ class PageRouteBuilder<T> extends PageRoute<T> { ...@@ -110,13 +110,13 @@ class PageRouteBuilder<T> extends PageRoute<T> {
final bool maintainState; final bool maintainState;
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return pageBuilder(context, animation, forwardAnimation); return pageBuilder(context, animation, secondaryAnimation);
} }
@override @override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child) { Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return transitionsBuilder(context, animation, forwardAnimation, child); return transitionsBuilder(context, animation, secondaryAnimation, child);
} }
} }
...@@ -152,8 +152,8 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> { ...@@ -152,8 +152,8 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
/// The animation for the route being pushed on top of this route. This /// The animation for the route being pushed on top of this route. This
/// animation lets this route coordinate with the entrance and exit transition /// animation lets this route coordinate with the entrance and exit transition
/// of routes pushed on top of this route. /// of routes pushed on top of this route.
Animation<double> get forwardAnimation => _forwardAnimation; Animation<double> get secondaryAnimation => _secondaryAnimation;
final ProxyAnimation _forwardAnimation = new ProxyAnimation(kAlwaysDismissedAnimation); final ProxyAnimation _secondaryAnimation = new ProxyAnimation(kAlwaysDismissedAnimation);
@override @override
void install(OverlayEntry insertionPoint) { void install(OverlayEntry insertionPoint) {
...@@ -187,19 +187,19 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> { ...@@ -187,19 +187,19 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
@override @override
void didPopNext(Route<dynamic> nextRoute) { void didPopNext(Route<dynamic> nextRoute) {
_updateForwardAnimation(nextRoute); _updateSecondaryAnimation(nextRoute);
super.didPopNext(nextRoute); super.didPopNext(nextRoute);
} }
@override @override
void didChangeNext(Route<dynamic> nextRoute) { void didChangeNext(Route<dynamic> nextRoute) {
_updateForwardAnimation(nextRoute); _updateSecondaryAnimation(nextRoute);
super.didChangeNext(nextRoute); super.didChangeNext(nextRoute);
} }
void _updateForwardAnimation(Route<dynamic> nextRoute) { void _updateSecondaryAnimation(Route<dynamic> nextRoute) {
if (nextRoute is TransitionRoute<dynamic> && canTransitionTo(nextRoute) && nextRoute.canTransitionFrom(this)) { if (nextRoute is TransitionRoute<dynamic> && canTransitionTo(nextRoute) && nextRoute.canTransitionFrom(this)) {
final Animation<double> current = _forwardAnimation.parent; final Animation<double> current = _secondaryAnimation.parent;
if (current != null) { if (current != null) {
if (current is TrainHoppingAnimation) { if (current is TrainHoppingAnimation) {
TrainHoppingAnimation newAnimation; TrainHoppingAnimation newAnimation;
...@@ -207,22 +207,22 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> { ...@@ -207,22 +207,22 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
current.currentTrain, current.currentTrain,
nextRoute._animation, nextRoute._animation,
onSwitchedTrain: () { onSwitchedTrain: () {
assert(_forwardAnimation.parent == newAnimation); assert(_secondaryAnimation.parent == newAnimation);
assert(newAnimation.currentTrain == nextRoute._animation); assert(newAnimation.currentTrain == nextRoute._animation);
_forwardAnimation.parent = newAnimation.currentTrain; _secondaryAnimation.parent = newAnimation.currentTrain;
newAnimation.dispose(); newAnimation.dispose();
} }
); );
_forwardAnimation.parent = newAnimation; _secondaryAnimation.parent = newAnimation;
current.dispose(); current.dispose();
} else { } else {
_forwardAnimation.parent = new TrainHoppingAnimation(current, nextRoute._animation); _secondaryAnimation.parent = new TrainHoppingAnimation(current, nextRoute._animation);
} }
} else { } else {
_forwardAnimation.parent = nextRoute._animation; _secondaryAnimation.parent = nextRoute._animation;
} }
} else { } else {
_forwardAnimation.parent = kAlwaysDismissedAnimation; _secondaryAnimation.parent = kAlwaysDismissedAnimation;
} }
} }
...@@ -437,7 +437,7 @@ class _ModalScopeState extends State<_ModalScope> { ...@@ -437,7 +437,7 @@ class _ModalScopeState extends State<_ModalScope> {
void initState() { void initState() {
super.initState(); super.initState();
config.route.animation?.addStatusListener(_animationStatusChanged); config.route.animation?.addStatusListener(_animationStatusChanged);
config.route.forwardAnimation?.addStatusListener(_animationStatusChanged); config.route.secondaryAnimation?.addStatusListener(_animationStatusChanged);
} }
@override @override
...@@ -448,7 +448,7 @@ class _ModalScopeState extends State<_ModalScope> { ...@@ -448,7 +448,7 @@ class _ModalScopeState extends State<_ModalScope> {
@override @override
void dispose() { void dispose() {
config.route.animation?.removeStatusListener(_animationStatusChanged); config.route.animation?.removeStatusListener(_animationStatusChanged);
config.route.forwardAnimation?.removeStatusListener(_animationStatusChanged); config.route.secondaryAnimation?.removeStatusListener(_animationStatusChanged);
super.dispose(); super.dispose();
} }
...@@ -483,7 +483,7 @@ class _ModalScopeState extends State<_ModalScope> { ...@@ -483,7 +483,7 @@ class _ModalScopeState extends State<_ModalScope> {
child: config.route.buildTransitions( child: config.route.buildTransitions(
context, context,
config.route.animation, config.route.animation,
config.route.forwardAnimation, config.route.secondaryAnimation,
new RepaintBoundary( new RepaintBoundary(
child: new PageStorage( child: new PageStorage(
key: config.route._subtreeKey, key: config.route._subtreeKey,
...@@ -577,26 +577,118 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T ...@@ -577,26 +577,118 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
/// * [animation] The animation for this route's transition. When entering, /// * [animation] The animation for this route's transition. When entering,
/// the animation runs forward from 0.0 to 1.0. When exiting, this animation /// the animation runs forward from 0.0 to 1.0. When exiting, this animation
/// runs backwards from 1.0 to 0.0. /// runs backwards from 1.0 to 0.0.
/// * [forwardAnimation] The animation for the route being pushed on top of /// * [secondaryAnimation] The animation for the route being pushed on top of
/// this route. This animation lets this route coordinate with the entrance /// this route. This animation lets this route coordinate with the entrance
/// and exit transition of routes pushed on top of this route. /// and exit transition of routes pushed on top of this route.
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation); Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation);
/// Override this method to wrap the route in a number of transition widgets. /// Override this method to wrap the [child] with one or more transition
/// /// widgets that define how the route arrives on and leaves the screen.
/// For example, to create a fade entrance transition, wrap the given child
/// widget in a [FadeTransition] using the given animation as the opacity.
/// ///
/// By default, the child is not wrapped in any transition widgets. /// By default, the child is not wrapped in any transition widgets.
/// ///
/// * [context] The context in which the route is being built. /// The buildTransitions method is typically used to define transitions
/// * [animation] The animation for this route's transition. When entering, /// that animate the new topmost route's comings and goings. When the
/// the animation runs forward from 0.0 to 1.0. When exiting, this animation /// [Navigator] pushes a route on the top of its stack, the new route's
/// runs backwards from 1.0 to 0.0. /// primary [animation] runs from 0.0 to 1.0. When the Navigator pops the
/// * [forwardAnimation] The animation for the route being pushed on top of /// topmost route, e.g. because the use pressed the back button, the
/// this route. This animation lets this route coordinate with the entrance /// primary animation runs from 1.0 to 0.0.
/// and exit transition of routes pushed on top of this route. ///
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child) { /// The following example uses the primary animation to drive a
/// [SlideTransition] that translates the top of the new route vertically
/// from the bottom of the screen when it is pushed on the Navigator's
/// stack. When the route is popped the SlideTransition translates the
/// route from the top of the screen back to the bottom.
///
/// ```dart
/// new PageRouteBuilder(
/// pageBuilder: (BuildContext context,
/// Animation<double> animation,
/// Animation<double> secondaryAnimation,
/// Widget child,
/// ) {
/// return new Scaffold(
/// appBar: new AppBar(title: new Text('Hello')),
/// body: new Center(
/// child: new Text('Hello World'),
/// ),
/// );
/// },
/// transitionsBuilder: (
/// BuildContext context,
/// Animation<double> animation,
/// Animation<double> secondaryAnimation,
/// Widget child,
/// ) {
/// return new SlideTransition(
/// position: new FractionalOffsetTween(
/// begin: FractionalOffset.bottomLeft,
/// end: FractionalOffset.topLeft
/// ).animate(animation),
/// child: child, // child is the value returned by pageBuilder
/// );
/// },
/// );
///```
///
/// We've used [PageRouteBuilder] to demonstrate the buildTransitions method
/// here. The body of an override of the buildTransitions method would be
/// defined in the same way.
///
/// When the Navigator pushes a route on the top of its stack, the
/// [secondaryAnimation] can be used to define how the route that was on
/// the top of the stack leaves the screen. Similarly when the topmost route
/// is popped, the secondaryAnimation can be used to define how the route
/// below it reappears on the screen. When the Navigator pushes a new route
/// on the top of its stack, the old topmost route's secondaryAnimation
/// runs from 0.0 to 1.0. When the Navigator pops the topmost route, the
/// secondaryAnimation for the route below it runs from 1.0 to 0.0.
///
/// The example below adds a transition that's driven by the
/// secondaryAnimation. When this route disappears because a new route has
/// been pushed on top of it, it translates in the opposite direction of
/// the new route. Likewise when the route is exposed because the topmost
/// route has been popped off.
///
/// ```dart
/// transitionsBuilder: (
/// BuildContext context,
/// Animation<double> animation,
/// Animation<double> secondaryAnimation,
/// Widget child,
/// ) {
/// return new SlideTransition(
/// position: new FractionalOffsetTween(
/// begin: FractionalOffset.bottomLeft,
/// end: FractionalOffset.topLeft,
/// ).animate(animation),
/// child: new SlideTransition(
/// position: new FractionalOffsetTween(
/// begin: FractionalOffset.topLeft,
/// end: FractionalOffset.bottomLeft,
/// ).animate(secondaryAnimation),
/// child: child,
/// ),
/// );
/// }
///```
///
/// In practice the secondaryAnimation is used pretty rarely.
///
/// * [context] The context in which the route is being built.
/// * [animation] When the [Navigator] pushes a route on the top of its stack,
/// the new route's primary [animation] runs from 0.0 to 1.0. When the Navigator
/// pops the topmost route this animation runs from 1.0 to 0.0.
/// * [secondaryAnimation] When the Navigator pushes a new route
/// on the top of its stack, the old topmost route's secondaryAnimation
/// runs from 0.0 to 1.0. When the Navigator pops the topmost route, the
/// secondaryAnimation for the route below it runs from 1.0 to 0.0.
Widget buildTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return child; return child;
} }
...@@ -607,7 +699,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T ...@@ -607,7 +699,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
void install(OverlayEntry insertionPoint) { void install(OverlayEntry insertionPoint) {
super.install(insertionPoint); super.install(insertionPoint);
_animationProxy = new ProxyAnimation(super.animation); _animationProxy = new ProxyAnimation(super.animation);
_forwardAnimationProxy = new ProxyAnimation(super.forwardAnimation); _secondaryAnimationProxy = new ProxyAnimation(super.secondaryAnimation);
} }
@override @override
...@@ -657,7 +749,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T ...@@ -657,7 +749,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
_offstage = value; _offstage = value;
}); });
_animationProxy.parent = _offstage ? kAlwaysCompleteAnimation : super.animation; _animationProxy.parent = _offstage ? kAlwaysCompleteAnimation : super.animation;
_forwardAnimationProxy.parent = _offstage ? kAlwaysDismissedAnimation : super.forwardAnimation; _secondaryAnimationProxy.parent = _offstage ? kAlwaysDismissedAnimation : super.secondaryAnimation;
} }
/// The build context for the subtree containing the primary content of this route. /// The build context for the subtree containing the primary content of this route.
...@@ -668,8 +760,8 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T ...@@ -668,8 +760,8 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
ProxyAnimation _animationProxy; ProxyAnimation _animationProxy;
@override @override
Animation<double> get forwardAnimation => _forwardAnimationProxy; Animation<double> get secondaryAnimation => _secondaryAnimationProxy;
ProxyAnimation _forwardAnimationProxy; ProxyAnimation _secondaryAnimationProxy;
/// Return the value of the first callback added with /// Return the value of the first callback added with
/// [addScopedWillPopCallback] that returns false. Otherwise return /// [addScopedWillPopCallback] that returns false. Otherwise return
...@@ -845,7 +937,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T ...@@ -845,7 +937,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
return new _ModalScope( return new _ModalScope(
key: _scopeKey, key: _scopeKey,
route: this, route: this,
page: buildPage(context, animation, forwardAnimation) page: buildPage(context, animation, secondaryAnimation)
// _ModalScope calls buildTransitions(), defined above // _ModalScope calls buildTransitions(), defined above
); );
} }
......
...@@ -20,7 +20,7 @@ class TestRoute<T> extends PageRoute<T> { ...@@ -20,7 +20,7 @@ class TestRoute<T> extends PageRoute<T> {
bool get maintainState => false; bool get maintainState => false;
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return child; return child;
} }
} }
......
...@@ -41,7 +41,7 @@ class TestRoute<T> extends PageRoute<T> { ...@@ -41,7 +41,7 @@ class TestRoute<T> extends PageRoute<T> {
bool get maintainState => false; bool get maintainState => false;
@override @override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) { Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return child; return child;
} }
} }
...@@ -94,7 +94,7 @@ void main() { ...@@ -94,7 +94,7 @@ void main() {
new TestTransition( new TestTransition(
childFirstHalf: new Text('C'), childFirstHalf: new Text('C'),
childSecondHalf: new Text('D'), childSecondHalf: new Text('D'),
animation: route.forwardAnimation animation: route.secondaryAnimation
), ),
] ]
); );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment