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