Commit aabd1ce4 authored by Adam Barth's avatar Adam Barth

Merge pull request #1317 from abarth/port_widgets

Port most of widgets to AnimationController
parents e4940a01 24872f69
......@@ -41,10 +41,9 @@ class Theme extends InheritedWidget {
}
}
/// An animated value that interpolates [BoxConstraint]s.
class AnimatedThemeDataValue extends AnimatedValue<ThemeData> {
AnimatedThemeDataValue(ThemeData begin, { ThemeData end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
/// An animated value that interpolates [ThemeData]s.
class ThemeDataTween extends Tween<ThemeData> {
ThemeDataTween({ ThemeData begin, ThemeData end }) : super(begin: begin, end: end);
ThemeData lerp(double t) => ThemeData.lerp(begin, end, t);
}
......@@ -71,18 +70,18 @@ class AnimatedTheme extends AnimatedWidgetBase {
}
class _AnimatedThemeState extends AnimatedWidgetBaseState<AnimatedTheme> {
AnimatedThemeDataValue _data;
ThemeDataTween _data;
void forEachVariable(VariableVisitor visitor) {
void forEachTween(TweenVisitor visitor) {
// TODO(ianh): Use constructor tear-offs when it becomes possible
_data = visitor(_data, config.data, (dynamic value) => new AnimatedThemeDataValue(value));
_data = visitor(_data, config.data, (dynamic value) => new ThemeDataTween(begin: value));
assert(_data != null);
}
Widget build(BuildContext context) {
return new Theme(
child: config.child,
data: _data.value
data: _data.evaluate(animation)
);
}
......
......@@ -72,23 +72,23 @@ class Dismissable extends StatefulComponent {
class _DismissableState extends State<Dismissable> {
void initState() {
super.initState();
_dismissPerformance = new Performance(duration: _kCardDismissDuration);
_dismissPerformance.addStatusListener((PerformanceStatus status) {
_dismissController = new AnimationController(duration: _kCardDismissDuration);
_dismissController.addStatusListener((PerformanceStatus status) {
if (status == PerformanceStatus.completed)
_handleDismissCompleted();
});
}
Performance _dismissPerformance;
Performance _resizePerformance;
AnimationController _dismissController;
AnimationController _resizeController;
Size _size;
double _dragExtent = 0.0;
bool _dragUnderway = false;
void dispose() {
_dismissPerformance?.stop();
_resizePerformance?.stop();
_dismissController?.stop();
_resizeController?.stop();
super.dispose();
}
......@@ -101,11 +101,11 @@ class _DismissableState extends State<Dismissable> {
void _handleDismissCompleted() {
if (!_dragUnderway)
_startResizePerformance();
_startResizeAnimation();
}
bool get _isActive {
return _size != null && (_dragUnderway || _dismissPerformance.isAnimating);
return _size != null && (_dragUnderway || _dismissController.isAnimating);
}
void _maybeCallOnResized() {
......@@ -118,21 +118,20 @@ class _DismissableState extends State<Dismissable> {
config.onDismissed();
}
void _startResizePerformance() {
void _startResizeAnimation() {
assert(_size != null);
assert(_dismissPerformance != null);
assert(_dismissPerformance.isCompleted);
assert(_resizePerformance == null);
assert(_dismissController != null);
assert(_dismissController.isCompleted);
assert(_resizeController == null);
setState(() {
_resizePerformance = new Performance()
..duration = _kCardResizeDuration
_resizeController = new AnimationController(duration: _kCardResizeDuration)
..addListener(_handleResizeProgressChanged);
_resizePerformance.play();
_resizeController.forward();
});
}
void _handleResizeProgressChanged() {
if (_resizePerformance.isCompleted)
if (_resizeController.isCompleted)
_maybeCallOnDismissed();
else
_maybeCallOnResized();
......@@ -141,18 +140,18 @@ class _DismissableState extends State<Dismissable> {
void _handleDragStart(_) {
setState(() {
_dragUnderway = true;
if (_dismissPerformance.isAnimating) {
_dragExtent = _dismissPerformance.progress * _size.width * _dragExtent.sign;
_dismissPerformance.stop();
if (_dismissController.isAnimating) {
_dragExtent = _dismissController.value * _size.width * _dragExtent.sign;
_dismissController.stop();
} else {
_dragExtent = 0.0;
_dismissPerformance.progress = 0.0;
_dismissController.value = 0.0;
}
});
}
void _handleDragUpdate(double delta) {
if (!_isActive || _dismissPerformance.isAnimating)
if (!_isActive || _dismissController.isAnimating)
return;
double oldDragExtent = _dragExtent;
......@@ -180,11 +179,11 @@ class _DismissableState extends State<Dismissable> {
// Rebuild to update the new drag endpoint.
// The sign of _dragExtent is part of our build state;
// the actual value is not, it's just used to configure
// the performances.
// the animations.
});
}
if (!_dismissPerformance.isAnimating)
_dismissPerformance.progress = _dragExtent.abs() / _size.width;
if (!_dismissController.isAnimating)
_dismissController.value = _dragExtent.abs() / _size.width;
}
bool _isFlingGesture(ui.Offset velocity) {
......@@ -217,20 +216,20 @@ class _DismissableState extends State<Dismissable> {
}
void _handleDragEnd(ui.Offset velocity) {
if (!_isActive || _dismissPerformance.isAnimating)
if (!_isActive || _dismissController.isAnimating)
return;
setState(() {
_dragUnderway = false;
if (_dismissPerformance.isCompleted) {
_startResizePerformance();
if (_dismissController.isCompleted) {
_startResizeAnimation();
} else if (_isFlingGesture(velocity)) {
double flingVelocity = _directionIsYAxis ? velocity.dy : velocity.dx;
_dragExtent = flingVelocity.sign;
_dismissPerformance.fling(velocity: flingVelocity.abs() * _kFlingVelocityScale);
} else if (_dismissPerformance.progress > _kDismissCardThreshold) {
_dismissPerformance.forward();
_dismissController.fling(velocity: flingVelocity.abs() * _kFlingVelocityScale);
} else if (_dismissController.value > _kDismissCardThreshold) {
_dismissController.forward();
} else {
_dismissPerformance.reverse();
_dismissController.reverse();
}
});
}
......@@ -250,20 +249,26 @@ class _DismissableState extends State<Dismissable> {
}
Widget build(BuildContext context) {
if (_resizePerformance != null) {
if (_resizeController != null) {
// make sure you remove this widget once it's been dismissed!
assert(_resizePerformance.status == PerformanceStatus.forward);
assert(_resizeController.status == PerformanceStatus.forward);
AnimatedValue<double> squashAxisExtent = new AnimatedValue<double>(
_directionIsYAxis ? _size.width : _size.height,
end: 0.0,
Animated<double> squashAxisExtent = new Tween<double>(
begin: _directionIsYAxis ? _size.width : _size.height,
end: 0.0
).animate(new CurvedAnimation(
parent: _resizeController,
curve: _kCardResizeTimeCurve
);
return new SquashTransition(
performance: _resizePerformance.view,
width: _directionIsYAxis ? squashAxisExtent : null,
height: !_directionIsYAxis ? squashAxisExtent : null
));
return new AnimatedBuilder(
animation: squashAxisExtent,
builder: (BuildContext context, Widget child) {
return new SizedBox(
width: _directionIsYAxis ? squashAxisExtent.value : null,
height: !_directionIsYAxis ? squashAxisExtent.value : null
);
}
);
}
......@@ -278,11 +283,10 @@ class _DismissableState extends State<Dismissable> {
child: new SizeObserver(
onSizeChanged: _handleSizeChanged,
child: new SlideTransition(
performance: _dismissPerformance.view,
position: new AnimatedValue<FractionalOffset>(
FractionalOffset.zero,
position: new Tween<FractionalOffset>(
begin: FractionalOffset.zero,
end: _activeCardDragEndPoint
),
).animate(_dismissController),
child: config.child
)
)
......
......@@ -378,7 +378,7 @@ class HeroParty {
Animated<double> _currentAnimation;
void _clearCurrentPerformance() {
void _clearCurrentAnimation() {
_currentAnimation?.removeStatusListener(_handleUpdate);
_currentAnimation = null;
}
......@@ -386,7 +386,7 @@ class HeroParty {
void setAnimation(Animated<double> animation) {
assert(animation != null || _heroes.length == 0);
if (animation != _currentAnimation) {
_clearCurrentPerformance();
_clearCurrentAnimation();
_currentAnimation = animation;
_currentAnimation?.addStatusListener(_handleUpdate);
}
......@@ -402,7 +402,7 @@ class HeroParty {
source._resetChild();
}
_heroes.clear();
_clearCurrentPerformance();
_clearCurrentAnimation();
if (onQuestFinished != null)
onQuestFinished();
}
......
......@@ -10,17 +10,15 @@ import 'framework.dart';
import 'package:vector_math/vector_math_64.dart';
/// An animated value that interpolates [BoxConstraint]s.
class AnimatedBoxConstraintsValue extends AnimatedValue<BoxConstraints> {
AnimatedBoxConstraintsValue(BoxConstraints begin, { BoxConstraints end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
class BoxConstraintsTween extends Tween<BoxConstraints> {
BoxConstraintsTween({ BoxConstraints begin, BoxConstraints end }) : super(begin: begin, end: end);
BoxConstraints lerp(double t) => BoxConstraints.lerp(begin, end, t);
}
/// An animated value that interpolates [Decoration]s.
class AnimatedDecorationValue extends AnimatedValue<Decoration> {
AnimatedDecorationValue(Decoration begin, { Decoration end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
class DecorationTween extends Tween<Decoration> {
DecorationTween({ Decoration begin, Decoration end }) : super(begin: begin, end: end);
Decoration lerp(double t) {
if (begin == null && end == null)
......@@ -32,9 +30,8 @@ class AnimatedDecorationValue extends AnimatedValue<Decoration> {
}
/// An animated value that interpolates [EdgeDims].
class AnimatedEdgeDimsValue extends AnimatedValue<EdgeDims> {
AnimatedEdgeDimsValue(EdgeDims begin, { EdgeDims end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
class EdgeDimsTween extends Tween<EdgeDims> {
EdgeDimsTween({ EdgeDims begin, EdgeDims end }) : super(begin: begin, end: end);
EdgeDims lerp(double t) => EdgeDims.lerp(begin, end, t);
}
......@@ -42,9 +39,8 @@ class AnimatedEdgeDimsValue extends AnimatedValue<EdgeDims> {
/// An animated value that interpolates [Matrix4]s.
///
/// Currently this class works only for translations.
class AnimatedMatrix4Value extends AnimatedValue<Matrix4> {
AnimatedMatrix4Value(Matrix4 begin, { Matrix4 end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
class Matrix4Tween extends Tween<Matrix4> {
Matrix4Tween({ Matrix4 begin, Matrix4 end }) : super(begin: begin, end: end);
Matrix4 lerp(double t) {
// TODO(mpcomplete): Animate the full matrix. Will animating the cells
......@@ -82,113 +78,107 @@ abstract class AnimatedWidgetBase extends StatefulComponent {
}
}
typedef AnimatedValue<T> VariableConstructor<T>(T targetValue);
typedef AnimatedValue<T> VariableVisitor<T>(AnimatedValue<T> variable, T targetValue, VariableConstructor<T> constructor);
typedef Tween<T> TweenConstructor<T>(T targetValue);
typedef Tween<T> TweenVisitor<T>(Tween<T> tween, T targetValue, TweenConstructor<T> constructor);
abstract class AnimatedWidgetBaseState<T extends AnimatedWidgetBase> extends State<T> {
Performance _performanceController;
PerformanceView _performance;
AnimationController _controller;
Animated<double> get animation => _animation;
Animated<double> _animation;
void initState() {
super.initState();
_performanceController = new Performance(
_controller = new AnimationController(
duration: config.duration,
debugLabel: '${config.toStringShort()}'
);
)..addListener(_handleAnimationChanged);
_updateCurve();
_configAllVariables();
_constructTweens();
}
void didUpdateConfig(T oldConfig) {
if (config.curve != oldConfig.curve)
_updateCurve();
_performanceController.duration = config.duration;
if (_configAllVariables()) {
forEachVariable((AnimatedValue variable, dynamic targetValue, VariableConstructor<T> constructor) {
_updateBeginValue(variable); return variable;
_controller.duration = config.duration;
if (_constructTweens()) {
forEachTween((Tween tween, dynamic targetValue, TweenConstructor<T> constructor) {
_updateTween(tween, targetValue);
return tween;
});
_performanceController.progress = 0.0;
_performanceController.play();
_controller
..value = 0.0
..forward();
}
}
void _updateCurve() {
_performance?.removeListener(_updateAllVariables);
if (config.curve != null)
_performance = new CurvedPerformance(_performanceController, curve: config.curve);
_animation = new CurvedAnimation(parent: _controller, curve: config.curve);
else
_performance = _performanceController;
_performance.addListener(_updateAllVariables);
_animation = _controller;
}
void dispose() {
_performanceController.stop();
_controller.stop();
super.dispose();
}
void _updateVariable(Animatable variable) {
if (variable != null)
_performance.updateVariable(variable);
}
void _updateAllVariables() {
setState(() {
forEachVariable((AnimatedValue variable, dynamic targetValue, VariableConstructor<T> constructor) {
_updateVariable(variable); return variable;
});
});
void _handleAnimationChanged() {
setState(() { });
}
bool _updateEndValue(AnimatedValue variable, dynamic targetValue) {
if (targetValue == variable.end)
return false;
variable.end = targetValue;
return true;
bool _shouldAnimateTween(Tween tween, dynamic targetValue) {
return targetValue != (tween.end ?? tween.begin);
}
void _updateBeginValue(AnimatedValue variable) {
variable?.begin = variable.value;
void _updateTween(Tween tween, dynamic targetValue) {
if (tween == null)
return;
tween
..begin = tween.evaluate(_animation)
..end = targetValue;
}
bool _configAllVariables() {
bool startAnimation = false;
forEachVariable((AnimatedValue variable, dynamic targetValue, VariableConstructor<T> constructor) {
bool _constructTweens() {
bool shouldStartAnimation = false;
forEachTween((Tween tween, dynamic targetValue, TweenConstructor<T> constructor) {
if (targetValue != null) {
variable ??= constructor(targetValue);
if (_updateEndValue(variable, targetValue))
startAnimation = true;
tween ??= constructor(targetValue);
if (_shouldAnimateTween(tween, targetValue))
shouldStartAnimation = true;
} else {
variable = null;
tween = null;
}
return variable;
return tween;
});
return startAnimation;
return shouldStartAnimation;
}
/// Subclasses must implement this function by running through the following
/// steps for for each animatable facet in the class:
///
/// 1. Call the visitor callback with three arguments, the first argument
/// being the current value of the AnimatedValue<T> object that represents the
/// variable (initially null), the second argument, of type T, being the value
/// being the current value of the Tween<T> object that represents the
/// tween (initially null), the second argument, of type T, being the value
/// on the Widget (config) that represents the current target value of the
/// variable, and the third being a callback that takes a value T (which will
/// tween, and the third being a callback that takes a value T (which will
/// be the second argument to the visitor callback), and that returns an
/// AnimatedValue<T> object for the variable, configured with the given value
/// Tween<T> object for the tween, configured with the given value
/// as the begin value.
///
/// 2. Take the value returned from the callback, and store it. This is the
/// value to use as the current value the next time that the forEachVariable()
/// value to use as the current value the next time that the forEachTween()
/// method is called.
void forEachVariable(VariableVisitor visitor);
void forEachTween(TweenVisitor visitor);
}
/// A container that gradually changes its values over a period of time.
///
/// This class is useful for generating simple implicit transitions between
/// different parameters to [Container]. For more complex animations, you'll
/// likely want to use a subclass of [Transition] or control a [Performance]
/// yourself.
/// likely want to use a subclass of [Transition] or use an
/// [AnimationController] yourself.
class AnimatedContainer extends AnimatedWidgetBase {
AnimatedContainer({
Key key,
......@@ -260,38 +250,38 @@ class AnimatedContainer extends AnimatedWidgetBase {
}
class _AnimatedContainerState extends AnimatedWidgetBaseState<AnimatedContainer> {
AnimatedBoxConstraintsValue _constraints;
AnimatedDecorationValue _decoration;
AnimatedDecorationValue _foregroundDecoration;
AnimatedEdgeDimsValue _margin;
AnimatedEdgeDimsValue _padding;
AnimatedMatrix4Value _transform;
AnimatedValue<double> _width;
AnimatedValue<double> _height;
void forEachVariable(VariableVisitor visitor) {
BoxConstraintsTween _constraints;
DecorationTween _decoration;
DecorationTween _foregroundDecoration;
EdgeDimsTween _margin;
EdgeDimsTween _padding;
Matrix4Tween _transform;
Tween<double> _width;
Tween<double> _height;
void forEachTween(TweenVisitor visitor) {
// TODO(ianh): Use constructor tear-offs when it becomes possible
_constraints = visitor(_constraints, config.constraints, (dynamic value) => new AnimatedBoxConstraintsValue(value));
_decoration = visitor(_decoration, config.decoration, (dynamic value) => new AnimatedDecorationValue(value));
_foregroundDecoration = visitor(_foregroundDecoration, config.foregroundDecoration, (dynamic value) => new AnimatedDecorationValue(value));
_margin = visitor(_margin, config.margin, (dynamic value) => new AnimatedEdgeDimsValue(value));
_padding = visitor(_padding, config.padding, (dynamic value) => new AnimatedEdgeDimsValue(value));
_transform = visitor(_transform, config.transform, (dynamic value) => new AnimatedMatrix4Value(value));
_width = visitor(_width, config.width, (dynamic value) => new AnimatedValue<double>(value));
_height = visitor(_height, config.height, (dynamic value) => new AnimatedValue<double>(value));
_constraints = visitor(_constraints, config.constraints, (dynamic value) => new BoxConstraintsTween(begin: value));
_decoration = visitor(_decoration, config.decoration, (dynamic value) => new DecorationTween(begin: value));
_foregroundDecoration = visitor(_foregroundDecoration, config.foregroundDecoration, (dynamic value) => new DecorationTween(begin: value));
_margin = visitor(_margin, config.margin, (dynamic value) => new EdgeDimsTween(begin: value));
_padding = visitor(_padding, config.padding, (dynamic value) => new EdgeDimsTween(begin: value));
_transform = visitor(_transform, config.transform, (dynamic value) => new Matrix4Tween(begin: value));
_width = visitor(_width, config.width, (dynamic value) => new Tween<double>(begin: value));
_height = visitor(_height, config.height, (dynamic value) => new Tween<double>(begin: value));
}
Widget build(BuildContext context) {
return new Container(
child: config.child,
constraints: _constraints?.value,
decoration: _decoration?.value,
foregroundDecoration: _foregroundDecoration?.value,
margin: _margin?.value,
padding: _padding?.value,
transform: _transform?.value,
width: _width?.value,
height: _height?.value
constraints: _constraints?.evaluate(animation),
decoration: _decoration?.evaluate(animation),
foregroundDecoration: _foregroundDecoration?.evaluate(animation),
margin: _margin?.evaluate(animation),
padding: _padding?.evaluate(animation),
transform: _transform?.evaluate(animation),
width: _width?.evaluate(animation),
height: _height?.evaluate(animation)
);
}
......@@ -381,32 +371,32 @@ class AnimatedPositioned extends AnimatedWidgetBase {
}
class _AnimatedPositionedState extends AnimatedWidgetBaseState<AnimatedPositioned> {
AnimatedValue<double> _left;
AnimatedValue<double> _top;
AnimatedValue<double> _right;
AnimatedValue<double> _bottom;
AnimatedValue<double> _width;
AnimatedValue<double> _height;
void forEachVariable(VariableVisitor visitor) {
Tween<double> _left;
Tween<double> _top;
Tween<double> _right;
Tween<double> _bottom;
Tween<double> _width;
Tween<double> _height;
void forEachTween(TweenVisitor visitor) {
// TODO(ianh): Use constructor tear-offs when it becomes possible
_left = visitor(_left, config.left, (dynamic value) => new AnimatedValue<double>(value));
_top = visitor(_top, config.top, (dynamic value) => new AnimatedValue<double>(value));
_right = visitor(_right, config.right, (dynamic value) => new AnimatedValue<double>(value));
_bottom = visitor(_bottom, config.bottom, (dynamic value) => new AnimatedValue<double>(value));
_width = visitor(_width, config.width, (dynamic value) => new AnimatedValue<double>(value));
_height = visitor(_height, config.height, (dynamic value) => new AnimatedValue<double>(value));
_left = visitor(_left, config.left, (dynamic value) => new Tween<double>(begin: value));
_top = visitor(_top, config.top, (dynamic value) => new Tween<double>(begin: value));
_right = visitor(_right, config.right, (dynamic value) => new Tween<double>(begin: value));
_bottom = visitor(_bottom, config.bottom, (dynamic value) => new Tween<double>(begin: value));
_width = visitor(_width, config.width, (dynamic value) => new Tween<double>(begin: value));
_height = visitor(_height, config.height, (dynamic value) => new Tween<double>(begin: value));
}
Widget build(BuildContext context) {
return new Positioned(
child: config.child,
left: _left?.value,
top: _top?.value,
right: _right?.value,
bottom: _bottom?.value,
width: _width?.value,
height: _height?.value
left: _left?.evaluate(animation),
top: _top?.evaluate(animation),
right: _right?.evaluate(animation),
bottom: _bottom?.evaluate(animation),
width: _width?.evaluate(animation),
height: _height?.evaluate(animation)
);
}
......
......@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/animation.dart';
import 'package:flutter/rendering.dart';
......@@ -42,7 +41,7 @@ class MimicOverlayEntry {
// Animation state
GlobalKey _targetKey;
Curve _curve;
Performance _performance;
AnimationController _controller;
/// Animate the entry to the location of the widget that has the given target key.
///
......@@ -63,10 +62,10 @@ class MimicOverlayEntry {
_targetKey = targetKey;
_curve = curve;
// TODO(abarth): Support changing the animation target when in flight.
assert(_performance == null);
_performance = new Performance(duration: duration)
assert(_controller == null);
_controller = new AnimationController(duration: duration)
..addListener(_overlayEntry.markNeedsBuild);
return _performance.play();
return _controller.forward();
}
/// Cause the overlay entry to rebuild during the next pipeline flush.
......@@ -84,8 +83,8 @@ class MimicOverlayEntry {
void dispose() {
_targetKey = null;
_curve = null;
_performance?.stop();
_performance = null;
_controller?.stop();
_controller = null;
_key.stopMimic();
_key = null;
_overlayEntry.remove();
......@@ -98,16 +97,14 @@ class MimicOverlayEntry {
Rect globalBounds = _initialGlobalBounds;
Point globalPosition = globalBounds.topLeft;
if (_targetKey != null) {
assert(_performance != null);
assert(_controller != null);
assert(_curve != null);
RenderBox box = _targetKey.currentContext?.findRenderObject();
if (box != null) {
// TODO(abarth): Handle the case where the transform here isn't just a translation.
Point localPosition = box.localToGlobal(Point.origin);
double t = _curve.transform(_performance.progress);
// TODO(abarth): Add Point.lerp.
globalPosition = new Point(ui.lerpDouble(globalPosition.x, localPosition.x, t),
ui.lerpDouble(globalPosition.y, localPosition.y, t));
double t = _curve.transform(_controller.value);
globalPosition = Point.lerp(globalPosition, localPosition, t);
}
}
......
......@@ -96,7 +96,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
Animated<double> _animation;
AnimationController _controller;
/// Called to create the Performance object that will drive the transitions to
/// Called to create the animation controller that will drive the transitions to
/// this route from the previous one, and back to the previous route from this
/// one.
AnimationController createAnimationController() {
......@@ -105,8 +105,8 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
return new AnimationController(duration: duration, debugLabel: debugLabel);
}
/// Called to create the PerformanceView that exposes the current progress of
/// the transition controlled by the Performance object created by
/// Called to create the animation that exposes the current progress of
/// the transition controlled by the animation controller created by
/// [createAnimationController()].
Animated<double> createAnimation() {
assert(_controller != null);
......@@ -166,32 +166,32 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
}
void didPopNext(Route nextRoute) {
_updateForwardPerformance(nextRoute);
_updateForwardAnimation(nextRoute);
super.didPopNext(nextRoute);
}
void didChangeNext(Route nextRoute) {
_updateForwardPerformance(nextRoute);
_updateForwardAnimation(nextRoute);
super.didChangeNext(nextRoute);
}
void _updateForwardPerformance(Route nextRoute) {
void _updateForwardAnimation(Route nextRoute) {
if (nextRoute is TransitionRoute && canTransitionTo(nextRoute) && nextRoute.canTransitionFrom(this)) {
Animated<double> current = _forwardAnimation.masterAnimation;
if (current != null) {
if (current is TrainHoppingAnimation) {
TrainHoppingAnimation newPerformance;
newPerformance = new TrainHoppingAnimation(
TrainHoppingAnimation newAnimation;
newAnimation = new TrainHoppingAnimation(
current.currentTrain,
nextRoute.animation,
onSwitchedTrain: () {
assert(_forwardAnimation.masterAnimation == newPerformance);
assert(newPerformance.currentTrain == nextRoute.animation);
_forwardAnimation.masterAnimation = newPerformance.currentTrain;
newPerformance.dispose();
assert(_forwardAnimation.masterAnimation == newAnimation);
assert(newAnimation.currentTrain == nextRoute.animation);
_forwardAnimation.masterAnimation = newAnimation.currentTrain;
newAnimation.dispose();
}
);
_forwardAnimation.masterAnimation = newPerformance;
_forwardAnimation.masterAnimation = newAnimation;
current.dispose();
} else {
_forwardAnimation.masterAnimation = new TrainHoppingAnimation(current, nextRoute.animation);
......@@ -322,7 +322,7 @@ class _ModalScopeState extends State<_ModalScope> {
void _animationStatusChanged(PerformanceStatus status) {
setState(() {
// The performances' states are our build state, and they changed already.
// The animation's states are our build state, and they changed already.
});
}
......
......@@ -24,24 +24,24 @@ abstract class StatusTransitionComponent extends StatefulComponent {
class _StatusTransitionState extends State<StatusTransitionComponent> {
void initState() {
super.initState();
config.animation.addStatusListener(_performanceStatusChanged);
config.animation.addStatusListener(_animationStatusChanged);
}
void didUpdateConfig(StatusTransitionComponent oldConfig) {
if (config.animation != oldConfig.animation) {
oldConfig.animation.removeStatusListener(_performanceStatusChanged);
config.animation.addStatusListener(_performanceStatusChanged);
oldConfig.animation.removeStatusListener(_animationStatusChanged);
config.animation.addStatusListener(_animationStatusChanged);
}
}
void dispose() {
config.animation.removeStatusListener(_performanceStatusChanged);
config.animation.removeStatusListener(_animationStatusChanged);
super.dispose();
}
void _performanceStatusChanged(PerformanceStatus status) {
void _animationStatusChanged(PerformanceStatus status) {
setState(() {
// The performance's state is our build state, and it changed already.
// The animation's state is our build state, and it changed already.
});
}
......
......@@ -126,23 +126,25 @@ abstract class TransitionWithChild extends TransitionComponent {
Widget buildWithChild(BuildContext context, Widget child);
}
class SlideTransition extends TransitionWithChild {
class SlideTransition extends AnimatedComponent {
SlideTransition({
Key key,
this.position,
Animated<FractionalOffset> position,
PerformanceView performance,
this.transformHitTests: true,
Widget child
}) : super(key: key,
performance: performance,
child: child);
this.child
}) : position = position, super(key: key, animation: position);
final AnimatedValue<FractionalOffset> position;
bool transformHitTests;
final Animated<FractionalOffset> position;
final bool transformHitTests;
final Widget child;
Widget buildWithChild(BuildContext context, Widget child) {
performance.updateVariable(position);
return new FractionalTranslation(translation: position.value, transformHitTests: transformHitTests, child: child);
Widget build(BuildContext context) {
return new FractionalTranslation(
translation: position.value,
transformHitTests: transformHitTests,
child: child
);
}
}
......
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