Commit 24872f69 authored by Adam Barth's avatar Adam Barth

Port most of widgets to AnimationController

I've left transitions and enter_exit_transition out of this patch, but I've
converted the rest.
parent e4940a01
...@@ -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();
} }
......
...@@ -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