Commit ecb72f97 authored by Adam Barth's avatar Adam Barth

Merge pull request #1318 from abarth/finish_port

Port the remainder of the framework to AnimationController
parents aabd1ce4 b988a875
......@@ -18,7 +18,7 @@ class PageSelectorDemo extends StatelessComponent {
builder: (BuildContext context, Widget child) {
Color background = selection.value == iconName ? _selectedColor.end : _selectedColor.begin;
if (selection.valueIsChanging) {
// Then the selection's performance is animating from previousValue to value.
// Then the selection's animation is animating from previousValue to value.
if (selection.value == iconName)
background = _selectedColor.evaluate(animation);
else if (selection.previousValue == iconName)
......
......@@ -21,13 +21,13 @@ class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> {
parent: controller,
curve: new Interval(0.0, 0.9, curve: Curves.ease),
reverseCurve: Curves.ease
)..addStatusListener((PerformanceStatus status) {
if (status == PerformanceStatus.dismissed || status == PerformanceStatus.completed)
)..addStatusListener((AnimationStatus status) {
if (status == AnimationStatus.dismissed || status == AnimationStatus.completed)
reverseValueAnimationDirection();
});
}
Animated<double> animation;
Animation<double> animation;
AnimationController controller;
void handleTap() {
......
......@@ -33,10 +33,10 @@ class CardTransition extends StatelessComponent {
});
final Widget child;
final Animated<double> animation;
final Evaluatable<double> x;
final Evaluatable<double> opacity;
final Evaluatable<double> scale;
final Animation<double> animation;
final Animatable<double> x;
final Animatable<double> opacity;
final Animatable<double> scale;
Widget build(BuildContext context) {
return new AnimatedBuilder(
......@@ -63,7 +63,7 @@ class SmoothBlockState extends State<SmoothBlock> {
double _height = 100.0;
Widget _handleEnter(Animated<double> animation, Widget child) {
Widget _handleEnter(Animation<double> animation, Widget child) {
return new CardTransition(
x: new Tween<double>(begin: -200.0, end: 0.0),
opacity: new Tween<double>(begin: 0.0, end: 1.0),
......@@ -73,7 +73,7 @@ class SmoothBlockState extends State<SmoothBlock> {
);
}
Widget _handleExit(Animated<double> animation, Widget child) {
Widget _handleExit(Animation<double> animation, Widget child) {
return new CardTransition(
x: new Tween<double>(begin: 0.0, end: 200.0),
opacity: new Tween<double>(begin: 1.0, end: 0.0),
......
......@@ -7,13 +7,13 @@
/// This library depends only on core Dart libraries and the `newton` package.
library animation;
export 'src/animation/animated_value.dart';
export 'src/animation/animation.dart';
export 'src/animation/animation_controller.dart';
export 'src/animation/animations.dart';
export 'src/animation/clamped_simulation.dart';
export 'src/animation/curves.dart';
export 'src/animation/forces.dart';
export 'src/animation/listener_helpers.dart';
export 'src/animation/performance.dart';
export 'src/animation/scroll_behavior.dart';
export 'src/animation/simulation_stepper.dart';
export 'src/animation/ticker.dart';
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' show Color, Size, Rect;
import 'curves.dart';
/// The direction in which an animation is running.
enum AnimationDirection {
/// The animation is running from beginning to end.
forward,
/// The animation is running backwards, from end to beginning.
reverse
}
/// An interface describing a variable that changes as an animation progresses.
///
/// Animatable objects, by convention, must be cheap to create. This allows them
/// to be used in build functions in Widgets.
abstract class Animatable {
// TODO(ianh): replace mentions of this class with just mentioning AnimatedValue directly
/// Update the variable to a given time in an animation that is running in the given direction
void setProgress(double t, AnimationDirection direction);
}
/// An animated variable with a concrete type.
class AnimatedValue<T extends dynamic> implements Animatable {
AnimatedValue(this.begin, { this.end, this.curve, this.reverseCurve }) {
value = begin;
}
/// The current value of this variable.
T value;
/// The value this variable has at the beginning of the animation.
T begin;
/// The value this variable has at the end of the animation.
T end;
/// Returns the value this variable has at the given animation clock value.
T lerp(double t) => begin + (end - begin) * t;
/// The curve to use in the forward direction.
Curve curve;
/// The curve to use in the reverse direction.
///
/// If this field is null, uses [curve] in both directions.
Curve reverseCurve;
Curve _getActiveCurve(AnimationDirection direction) {
if (direction == AnimationDirection.forward || reverseCurve == null)
return curve;
return reverseCurve;
}
double transform(double t, AnimationDirection direction) {
Curve activeCurve = _getActiveCurve(direction);
if (activeCurve == null)
return t;
if (t == 0.0 || t == 1.0) {
assert(activeCurve.transform(t).round() == t);
return t;
}
return activeCurve.transform(t);
}
/// Updates the value of this variable according to the given animation clock
/// value and direction.
void setProgress(double t, AnimationDirection direction) {
if (end != null) {
t = transform(t, direction);
if (t == 0.0)
value = begin;
else if (t == 1.0)
value = end;
else
value = lerp(t);
}
}
String toString() => 'AnimatedValue(begin=$begin, end=$end, value=$value)';
}
/// An animated variable containing a color.
///
/// This class specializes the interpolation of AnimatedValue<Color> to be
/// appropriate for colors.
class AnimatedColorValue extends AnimatedValue<Color> {
AnimatedColorValue(Color begin, { Color end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
Color lerp(double t) => Color.lerp(begin, end, t);
}
/// An animated variable containing a size.
///
/// This class specializes the interpolation of AnimatedValue<Size> to be
/// appropriate for rectangles.
class AnimatedSizeValue extends AnimatedValue<Size> {
AnimatedSizeValue(Size begin, { Size end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
Size lerp(double t) => Size.lerp(begin, end, t);
}
/// An animated variable containing a rectangle.
///
/// This class specializes the interpolation of AnimatedValue<Rect> to be
/// appropriate for rectangles.
class AnimatedRectValue extends AnimatedValue<Rect> {
AnimatedRectValue(Rect begin, { Rect end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
Rect lerp(double t) => Rect.lerp(begin, end, t);
}
/// An animated variable containing a int.
class AnimatedIntValue extends AnimatedValue<int> {
AnimatedIntValue(int begin, { int end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
// The inherited lerp() function doesn't work with ints because it multiplies
// the begin and end types by a double, and int * double returns a double.
int lerp(double t) => (begin + (end - begin) * t).round();
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' show Color, Size, Rect, VoidCallback, lerpDouble;
/// The direction in which an animation is running.
enum AnimationDirection {
/// The animation is running from beginning to end.
forward,
/// The animation is running backwards, from end to beginning.
reverse
}
/// The status of an animation
enum AnimationStatus {
/// The animation is stopped at the beginning
dismissed,
/// The animation is running from beginning to end
forward,
/// The animation is running backwards, from end to beginning
reverse,
/// The animation is stopped at the end
completed,
}
typedef void AnimationStatusListener(AnimationStatus status);
abstract class Animation<T> {
const Animation();
/// Calls the listener every time the value of the animation changes.
void addListener(VoidCallback listener);
/// Stop calling the listener every time the value of the animation changes.
void removeListener(VoidCallback listener);
/// Calls listener every time the status of the animation changes.
void addStatusListener(AnimationStatusListener listener);
/// Stops calling the listener every time the status of the animation changes.
void removeStatusListener(AnimationStatusListener listener);
/// The current status of this animation.
AnimationStatus get status;
/// The current direction of the animation.
AnimationDirection get direction;
/// The current value of the animation.
T get value;
/// Whether this animation is stopped at the beginning.
bool get isDismissed => status == AnimationStatus.dismissed;
/// Whether this animation is stopped at the end.
bool get isCompleted => status == AnimationStatus.completed;
String toString() {
return '$runtimeType(${toStringDetails()})';
}
String toStringDetails() {
assert(status != null);
assert(direction != null);
String icon;
switch (status) {
case AnimationStatus.forward:
icon = '\u25B6'; // >
break;
case AnimationStatus.reverse:
icon = '\u25C0'; // <
break;
case AnimationStatus.completed:
switch (direction) {
case AnimationDirection.forward:
icon = '\u23ED'; // >>|
break;
case AnimationDirection.reverse:
icon = '\u29CF'; // <|
break;
}
break;
case AnimationStatus.dismissed:
switch (direction) {
case AnimationDirection.forward:
icon = '\u29D0'; // |>
break;
case AnimationDirection.reverse:
icon = '\u23EE'; // |<<
break;
}
break;
}
assert(icon != null);
return '$icon';
}
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:ui' show Color, Size, Rect, VoidCallback, lerpDouble;
import 'package:newton/newton.dart';
import 'animation.dart';
import 'forces.dart';
import 'listener_helpers.dart';
import 'simulation_stepper.dart';
class AnimationController extends Animation<double>
with EagerListenerMixin, LocalPerformanceListenersMixin, LocalPerformanceStatusListenersMixin {
AnimationController({ this.duration, double value, this.debugLabel }) {
_timeline = new SimulationStepper(_tick);
if (value != null)
_timeline.value = value.clamp(0.0, 1.0);
}
/// A label that is used in the [toString] output. Intended to aid with
/// identifying animation controller instances in debug output.
final String debugLabel;
/// Returns a [Animated<double>] for this animation controller,
/// so that a pointer to this object can be passed around without
/// allowing users of that pointer to mutate the AnimationController state.
Animation<double> get view => this;
/// The length of time this animation should last.
Duration duration;
SimulationStepper _timeline;
AnimationDirection get direction => _direction;
AnimationDirection _direction = AnimationDirection.forward;
/// The progress of this animation along the timeline.
///
/// Note: Setting this value stops the current animation.
double get value => _timeline.value.clamp(0.0, 1.0);
void set value(double t) {
stop();
_timeline.value = t.clamp(0.0, 1.0);
_checkStatusChanged();
}
/// Whether this animation is currently animating in either the forward or reverse direction.
bool get isAnimating => _timeline.isAnimating;
AnimationStatus get status {
if (!isAnimating && value == 1.0)
return AnimationStatus.completed;
if (!isAnimating && value == 0.0)
return AnimationStatus.dismissed;
return _direction == AnimationDirection.forward ?
AnimationStatus.forward :
AnimationStatus.reverse;
}
/// Starts running this animation forwards (towards the end).
Future forward() => play(AnimationDirection.forward);
/// Starts running this animation in reverse (towards the beginning).
Future reverse() => play(AnimationDirection.reverse);
/// Starts running this animation in the given direction.
Future play(AnimationDirection direction) {
_direction = direction;
return resume();
}
/// Resumes this animation in the most recent direction.
Future resume() {
return _animateTo(_direction == AnimationDirection.forward ? 1.0 : 0.0);
}
/// Stops running this animation.
void stop() {
_timeline.stop();
}
/// Releases any resources used by this object.
///
/// Same as stop().
void dispose() {
stop();
}
///
/// Flings the timeline with an optional force (defaults to a critically
/// damped spring) and initial velocity. If velocity is positive, the
/// animation will complete, otherwise it will dismiss.
Future fling({double velocity: 1.0, Force force}) {
force ??= kDefaultSpringForce;
_direction = velocity < 0.0 ? AnimationDirection.reverse : AnimationDirection.forward;
return _timeline.animateWith(force.release(value, velocity));
}
/// Starts running this animation in the forward direction, and
/// restarts the animation when it completes.
Future repeat({ double min: 0.0, double max: 1.0, Duration period }) {
period ??= duration;
return _timeline.animateWith(new _RepeatingSimulation(min, max, period));
}
AnimationStatus _lastStatus = AnimationStatus.dismissed;
void _checkStatusChanged() {
AnimationStatus currentStatus = status;
if (currentStatus != _lastStatus)
notifyStatusListeners(status);
_lastStatus = currentStatus;
}
Future _animateTo(double target) {
Duration remainingDuration = duration * (target - _timeline.value).abs();
_timeline.stop();
if (remainingDuration == Duration.ZERO)
return new Future.value();
return _timeline.animateTo(target, duration: remainingDuration);
}
void _tick(double t) {
notifyListeners();
_checkStatusChanged();
}
String toStringDetails() {
String paused = _timeline.isAnimating ? '' : '; paused';
String label = debugLabel == null ? '' : '; for $debugLabel';
String more = '${super.toStringDetails()} ${value.toStringAsFixed(3)}';
return '$more$paused$label';
}
}
class _RepeatingSimulation extends Simulation {
_RepeatingSimulation(this.min, this.max, Duration period)
: _periodInSeconds = period.inMicroseconds / Duration.MICROSECONDS_PER_SECOND {
assert(_periodInSeconds > 0.0);
}
final double min;
final double max;
final double _periodInSeconds;
double x(double timeInSeconds) {
assert(timeInSeconds >= 0.0);
final double t = (timeInSeconds / _periodInSeconds) % 1.0;
return lerpDouble(min, max, t);
}
double dx(double timeInSeconds) => 1.0;
bool isDone(double timeInSeconds) => false;
}
......@@ -4,58 +4,81 @@
import 'dart:ui' show VoidCallback;
import 'animated_value.dart';
import 'animation.dart';
import 'curves.dart';
import 'listener_helpers.dart';
import 'tween.dart';
class AlwaysCompleteAnimation extends Animated<double> {
class AlwaysCompleteAnimation extends Animation<double> {
const AlwaysCompleteAnimation();
// this performance never changes state
void addListener(VoidCallback listener) { }
void removeListener(VoidCallback listener) { }
void addStatusListener(PerformanceStatusListener listener) { }
void removeStatusListener(PerformanceStatusListener listener) { }
PerformanceStatus get status => PerformanceStatus.completed;
void addStatusListener(AnimationStatusListener listener) { }
void removeStatusListener(AnimationStatusListener listener) { }
AnimationStatus get status => AnimationStatus.completed;
AnimationDirection get direction => AnimationDirection.forward;
double get value => 1.0;
}
const AlwaysCompleteAnimation kAlwaysCompleteAnimation = const AlwaysCompleteAnimation();
class AlwaysDismissedAnimation extends Animated<double> {
class AlwaysDismissedAnimation extends Animation<double> {
const AlwaysDismissedAnimation();
// this performance never changes state
void addListener(VoidCallback listener) { }
void removeListener(VoidCallback listener) { }
void addStatusListener(PerformanceStatusListener listener) { }
void removeStatusListener(PerformanceStatusListener listener) { }
PerformanceStatus get status => PerformanceStatus.dismissed;
void addStatusListener(AnimationStatusListener listener) { }
void removeStatusListener(AnimationStatusListener listener) { }
AnimationStatus get status => AnimationStatus.dismissed;
AnimationDirection get direction => AnimationDirection.forward;
double get value => 0.0;
}
const AlwaysDismissedAnimation kAlwaysDismissedAnimation = const AlwaysDismissedAnimation();
class ProxyAnimation extends Animated<double>
class AlwaysStoppedAnimation extends Animation<double> {
const AlwaysStoppedAnimation(this.value);
final double value;
void addListener(VoidCallback listener) { }
void removeListener(VoidCallback listener) { }
void addStatusListener(AnimationStatusListener listener) { }
void removeStatusListener(AnimationStatusListener listener) { }
AnimationStatus get status => AnimationStatus.forward;
AnimationDirection get direction => AnimationDirection.forward;
}
abstract class ProxyAnimatedMixin {
Animation<double> get parent;
void addListener(VoidCallback listener) => parent.addListener(listener);
void removeListener(VoidCallback listener) => parent.removeListener(listener);
void addStatusListener(AnimationStatusListener listener) => parent.addStatusListener(listener);
void removeStatusListener(AnimationStatusListener listener) => parent.removeStatusListener(listener);
AnimationStatus get status => parent.status;
AnimationDirection get direction => parent.direction;
}
class ProxyAnimation extends Animation<double>
with LazyListenerMixin, LocalPerformanceListenersMixin, LocalPerformanceStatusListenersMixin {
ProxyAnimation([Animated<double> animation]) {
ProxyAnimation([Animation<double> animation]) {
_masterAnimation = animation;
if (_masterAnimation == null) {
_status = PerformanceStatus.dismissed;
_status = AnimationStatus.dismissed;
_direction = AnimationDirection.forward;
_value = 0.0;
}
}
PerformanceStatus _status;
AnimationStatus _status;
AnimationDirection _direction;
double _value;
Animated<double> get masterAnimation => _masterAnimation;
Animated<double> _masterAnimation;
void set masterAnimation(Animated<double> value) {
Animation<double> get masterAnimation => _masterAnimation;
Animation<double> _masterAnimation;
void set masterAnimation(Animation<double> value) {
if (value == _masterAnimation)
return;
if (_masterAnimation != null) {
......@@ -93,16 +116,16 @@ class ProxyAnimation extends Animated<double>
}
}
PerformanceStatus get status => _masterAnimation != null ? _masterAnimation.status : _status;
AnimationStatus get status => _masterAnimation != null ? _masterAnimation.status : _status;
AnimationDirection get direction => _masterAnimation != null ? _masterAnimation.direction : _direction;
double get value => _masterAnimation != null ? _masterAnimation.value : _value;
}
class ReverseAnimation extends Animated<double>
class ReverseAnimation extends Animation<double>
with LazyListenerMixin, LocalPerformanceStatusListenersMixin {
ReverseAnimation(this.masterAnimation);
final Animated<double> masterAnimation;
final Animation<double> masterAnimation;
void addListener(VoidCallback listener) {
didRegisterListener();
......@@ -121,20 +144,20 @@ class ReverseAnimation extends Animated<double>
masterAnimation.removeStatusListener(_statusChangeHandler);
}
void _statusChangeHandler(PerformanceStatus status) {
void _statusChangeHandler(AnimationStatus status) {
notifyStatusListeners(_reverseStatus(status));
}
PerformanceStatus get status => _reverseStatus(masterAnimation.status);
AnimationStatus get status => _reverseStatus(masterAnimation.status);
AnimationDirection get direction => _reverseDirection(masterAnimation.direction);
double get value => 1.0 - masterAnimation.value;
PerformanceStatus _reverseStatus(PerformanceStatus status) {
AnimationStatus _reverseStatus(AnimationStatus status) {
switch (status) {
case PerformanceStatus.forward: return PerformanceStatus.reverse;
case PerformanceStatus.reverse: return PerformanceStatus.forward;
case PerformanceStatus.completed: return PerformanceStatus.dismissed;
case PerformanceStatus.dismissed: return PerformanceStatus.completed;
case AnimationStatus.forward: return AnimationStatus.reverse;
case AnimationStatus.reverse: return AnimationStatus.forward;
case AnimationStatus.completed: return AnimationStatus.dismissed;
case AnimationStatus.dismissed: return AnimationStatus.completed;
}
}
......@@ -146,6 +169,64 @@ class ReverseAnimation extends Animated<double>
}
}
class CurvedAnimation extends Animation<double> with ProxyAnimatedMixin {
CurvedAnimation({
this.parent,
this.curve: Curves.linear,
this.reverseCurve
}) {
assert(parent != null);
assert(curve != null);
parent.addStatusListener(_handleStatusChanged);
}
final Animation<double> parent;
/// The curve to use in the forward direction.
Curve curve;
/// The curve to use in the reverse direction.
///
/// If this field is null, uses [curve] in both directions.
Curve reverseCurve;
/// The direction used to select the current curve.
///
/// The curve direction is only reset when we hit the beginning or the end of
/// the timeline to avoid discontinuities in the value of any variables this
/// a animation is used to animate.
AnimationDirection _curveDirection;
void _handleStatusChanged(AnimationStatus status) {
switch (status) {
case AnimationStatus.dismissed:
case AnimationStatus.completed:
_curveDirection = null;
break;
case AnimationStatus.forward:
_curveDirection ??= AnimationDirection.forward;
break;
case AnimationStatus.reverse:
_curveDirection ??= AnimationDirection.reverse;
break;
}
}
double get value {
final bool useForwardCurve = reverseCurve == null || (_curveDirection ?? parent.direction) == AnimationDirection.forward;
Curve activeCurve = useForwardCurve ? curve : reverseCurve;
double t = parent.value;
if (activeCurve == null)
return t;
if (t == 0.0 || t == 1.0) {
assert(activeCurve.transform(t).round() == t);
return t;
}
return activeCurve.transform(t);
}
}
enum _TrainHoppingMode { minimize, maximize }
/// This animation starts by proxying one animation, but can be given a
......@@ -158,7 +239,7 @@ enum _TrainHoppingMode { minimize, maximize }
/// listeners of its own, instead of shutting down when all its listeners are
/// removed, it exposes a [dispose()] method. Call this method to shut this
/// object down.
class TrainHoppingAnimation extends Animated<double>
class TrainHoppingAnimation extends Animation<double>
with EagerListenerMixin, LocalPerformanceListenersMixin, LocalPerformanceStatusListenersMixin {
TrainHoppingAnimation(this._currentTrain, this._nextTrain, { this.onSwitchedTrain }) {
assert(_currentTrain != null);
......@@ -180,15 +261,15 @@ class TrainHoppingAnimation extends Animated<double>
assert(_mode != null);
}
Animated<double> get currentTrain => _currentTrain;
Animated<double> _currentTrain;
Animated<double> _nextTrain;
Animation<double> get currentTrain => _currentTrain;
Animation<double> _currentTrain;
Animation<double> _nextTrain;
_TrainHoppingMode _mode;
VoidCallback onSwitchedTrain;
PerformanceStatus _lastStatus;
void _statusChangeHandler(PerformanceStatus status) {
AnimationStatus _lastStatus;
void _statusChangeHandler(AnimationStatus status) {
assert(_currentTrain != null);
if (status != _lastStatus) {
notifyListeners();
......@@ -197,7 +278,7 @@ class TrainHoppingAnimation extends Animated<double>
assert(_lastStatus != null);
}
PerformanceStatus get status => _currentTrain.status;
AnimationStatus get status => _currentTrain.status;
AnimationDirection get direction => _currentTrain.direction;
double _lastValue;
......
......@@ -4,22 +4,7 @@
import 'dart:ui' show VoidCallback;
/// The status of an animation
enum PerformanceStatus {
/// The animation is stopped at the beginning
dismissed,
/// The animation is running from beginning to end
forward,
/// The animation is running backwards, from end to beginning
reverse,
/// The animation is stopped at the end
completed,
}
typedef void PerformanceStatusListener(PerformanceStatus status);
import 'animation.dart';
abstract class _ListenerMixin {
void didRegisterListener();
......@@ -71,18 +56,18 @@ abstract class LocalPerformanceListenersMixin extends _ListenerMixin {
}
abstract class LocalPerformanceStatusListenersMixin extends _ListenerMixin {
final List<PerformanceStatusListener> _statusListeners = <PerformanceStatusListener>[];
void addStatusListener(PerformanceStatusListener listener) {
final List<AnimationStatusListener> _statusListeners = <AnimationStatusListener>[];
void addStatusListener(AnimationStatusListener listener) {
didRegisterListener();
_statusListeners.add(listener);
}
void removeStatusListener(PerformanceStatusListener listener) {
void removeStatusListener(AnimationStatusListener listener) {
_statusListeners.remove(listener);
didUnregisterListener();
}
void notifyStatusListeners(PerformanceStatus status) {
List<PerformanceStatusListener> localListeners = new List<PerformanceStatusListener>.from(_statusListeners);
for (PerformanceStatusListener listener in localListeners)
void notifyStatusListeners(AnimationStatus status) {
List<AnimationStatusListener> localListeners = new List<AnimationStatusListener>.from(_statusListeners);
for (AnimationStatusListener listener in localListeners)
listener(status);
}
}
This diff is collapsed.
......@@ -5,31 +5,32 @@
import 'dart:async';
import 'package:newton/newton.dart';
import 'animated_value.dart';
import 'curves.dart';
import 'ticker.dart';
/// A simulation that varies from [begin] to [end] over [duration] using [curve].
///
/// This class is an adaptor between the Simulation interface and the
/// AnimatedValue interface.
/// A simulation that varies from begin to end over duration using curve.
class _TweenSimulation extends Simulation {
_TweenSimulation(double begin, double end, Duration duration, Curve curve)
: _durationInSeconds = duration.inMicroseconds / Duration.MICROSECONDS_PER_SECOND,
_tween = new AnimatedValue<double>(begin, end: end, curve: curve) {
_TweenSimulation(this._begin, this._end, Duration duration, this._curve)
: _durationInSeconds = duration.inMicroseconds / Duration.MICROSECONDS_PER_SECOND {
assert(_durationInSeconds > 0.0);
assert(begin != null);
assert(end != null);
assert(_begin != null);
assert(_end != null);
}
final double _durationInSeconds;
final AnimatedValue<double> _tween;
final double _begin;
final double _end;
final Curve _curve;
double x(double timeInSeconds) {
assert(timeInSeconds >= 0.0);
final double t = (timeInSeconds / _durationInSeconds).clamp(0.0, 1.0);
_tween.setProgress(t, AnimationDirection.forward);
return _tween.value;
double t = (timeInSeconds / _durationInSeconds).clamp(0.0, 1.0);
if (t == 0.0)
return _begin;
else if (t == 1.0)
return _end;
else
return _begin + (_end - _begin) * _curve.transform(t);
}
double dx(double timeInSeconds) => 1.0;
......
......@@ -167,7 +167,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
return BottomSheet.createAnimationController();
}
Widget buildPage(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation) {
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
return new _ModalBottomSheet(route: this);
}
}
......
......@@ -128,11 +128,11 @@ class _DialogRoute<T> extends PopupRoute<T> {
bool get barrierDismissable => true;
Color get barrierColor => Colors.black54;
Widget buildPage(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation) {
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
return child;
}
Widget buildTransitions(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation, Widget child) {
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child) {
return new FadeTransition(
opacity: new CurvedAnimation(
parent: animation,
......
......@@ -92,18 +92,18 @@ class DrawerControllerState extends State<DrawerController> {
}
}
void _animationStatusChanged(PerformanceStatus status) {
void _animationStatusChanged(AnimationStatus status) {
switch (status) {
case PerformanceStatus.forward:
case AnimationStatus.forward:
_ensureHistoryEntry();
break;
case PerformanceStatus.reverse:
case AnimationStatus.reverse:
_historyEntry?.remove();
_historyEntry = null;
break;
case PerformanceStatus.dismissed:
case AnimationStatus.dismissed:
break;
case PerformanceStatus.completed:
case AnimationStatus.completed:
break;
}
}
......@@ -155,7 +155,7 @@ class DrawerControllerState extends State<DrawerController> {
final GlobalKey _gestureDetectorKey = new GlobalKey();
Widget build(BuildContext context) {
if (_controller.status == PerformanceStatus.dismissed) {
if (_controller.status == AnimationStatus.dismissed) {
return new Align(
alignment: const FractionalOffset(0.0, 0.5),
child: new GestureDetector(
......
......@@ -193,7 +193,7 @@ class _DropDownRoute<T> extends PopupRoute<_DropDownRouteResult<T>> {
);
}
Widget buildPage(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation) {
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
return new _DropDownMenu(route: this);
}
}
......
......@@ -40,7 +40,7 @@ class FloatingActionButton extends StatefulComponent {
}
class _FloatingActionButtonState extends State<FloatingActionButton> {
Animated<double> _childSegue;
Animation<double> _childSegue;
AnimationController _childSegueController;
void initState() {
......
......@@ -367,10 +367,10 @@ class _InkSplash extends InkFeature implements InkSplash {
final bool clipToReferenceBox;
final bool repositionToReferenceBox;
Animated<double> _radius;
Animation<double> _radius;
AnimationController _radiusController;
Animated<int> _alpha;
Animation<int> _alpha;
AnimationController _alphaController;
void confirm() {
......@@ -385,8 +385,8 @@ class _InkSplash extends InkFeature implements InkSplash {
_alphaController.forward();
}
void _handleAlphaStatusChanged(PerformanceStatus status) {
if (status == PerformanceStatus.completed)
void _handleAlphaStatusChanged(AnimationStatus status) {
if (status == AnimationStatus.completed)
dispose();
}
......@@ -456,7 +456,7 @@ class _InkHighlight extends InkFeature implements InkHighlight {
bool get active => _active;
bool _active = true;
Animated<int> _alpha;
Animation<int> _alpha;
AnimationController _alphaController;
void activate() {
......@@ -469,8 +469,8 @@ class _InkHighlight extends InkFeature implements InkHighlight {
_alphaController.reverse();
}
void _handleAlphaStatusChanged(PerformanceStatus status) {
if (status == PerformanceStatus.dismissed && !_active)
void _handleAlphaStatusChanged(AnimationStatus status) {
if (status == AnimationStatus.dismissed && !_active)
dispose();
}
......
......@@ -10,7 +10,7 @@ import 'package:flutter/widgets.dart';
class _MaterialPageTransition extends AnimatedComponent {
_MaterialPageTransition({
Key key,
Animated<double> animation,
Animation<double> animation,
this.child
}) : super(
key: key,
......@@ -57,7 +57,7 @@ class MaterialPageRoute<T> extends PageRoute<T> {
Color get barrierColor => null;
bool canTransitionFrom(TransitionRoute nextRoute) => false;
Widget buildPage(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation) {
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
Widget result = builder(context);
assert(() {
if (result == null)
......@@ -68,7 +68,7 @@ class MaterialPageRoute<T> extends PageRoute<T> {
return result;
}
Widget buildTransitions(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation, Widget child) {
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child) {
return new _MaterialPageTransition(
animation: animation,
child: child
......
......@@ -132,7 +132,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
return position;
}
Animated<double> createAnimation() {
Animation<double> createAnimation() {
return new CurvedAnimation(
parent: super.createAnimation(),
reverseCurve: new Interval(0.0, _kMenuCloseIntervalEnd)
......@@ -143,7 +143,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
bool get barrierDismissable => true;
Color get barrierColor => null;
Widget buildPage(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation) {
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
return new _PopupMenu(route: this);
}
}
......
......@@ -38,15 +38,15 @@ abstract class ProgressIndicator extends StatefulComponent {
}
class _ProgressIndicatorState extends State<ProgressIndicator> {
Animated<double> _animation;
Animation<double> _animation;
AnimationController _controller;
void initState() {
super.initState();
_controller = new AnimationController(
duration: const Duration(milliseconds: 1500)
)..addStatusListener((PerformanceStatus status) {
if (status == PerformanceStatus.completed)
)..addStatusListener((AnimationStatus status) {
if (status == AnimationStatus.completed)
_restartAnimation();
})..forward();
_animation = new CurvedAnimation(parent: _controller, curve: Curves.ease);
......
......@@ -227,9 +227,9 @@ class ScaffoldState extends State<Scaffold> {
return controller;
}
void _handleSnackBarStatusChange(PerformanceStatus status) {
void _handleSnackBarStatusChange(AnimationStatus status) {
switch (status) {
case PerformanceStatus.dismissed:
case AnimationStatus.dismissed:
assert(_snackBars.isNotEmpty);
setState(() {
_snackBars.removeFirst();
......@@ -237,21 +237,21 @@ class ScaffoldState extends State<Scaffold> {
if (_snackBars.isNotEmpty)
_snackBarController.forward();
break;
case PerformanceStatus.completed:
case AnimationStatus.completed:
setState(() {
assert(_snackBarTimer == null);
// build will create a new timer if necessary to dismiss the snack bar
});
break;
case PerformanceStatus.forward:
case PerformanceStatus.reverse:
case AnimationStatus.forward:
case AnimationStatus.reverse:
break;
}
}
void _hideSnackBar() {
assert(_snackBarController.status == PerformanceStatus.forward ||
_snackBarController.status == PerformanceStatus.completed);
assert(_snackBarController.status == AnimationStatus.forward ||
_snackBarController.status == AnimationStatus.completed);
_snackBars.first._completer.complete();
_snackBarController.reverse();
_snackBarTimer = null;
......@@ -449,7 +449,7 @@ class _PersistentBottomSheetState extends State<_PersistentBottomSheet> {
void initState() {
super.initState();
assert(config.animationController.status == PerformanceStatus.forward);
assert(config.animationController.status == AnimationStatus.forward);
config.animationController.addStatusListener(_handleStatusChange);
}
......@@ -467,8 +467,8 @@ class _PersistentBottomSheetState extends State<_PersistentBottomSheet> {
config.animationController.reverse();
}
void _handleStatusChange(PerformanceStatus status) {
if (status == PerformanceStatus.dismissed && config.onDismissed != null)
void _handleStatusChange(AnimationStatus status) {
if (status == AnimationStatus.dismissed && config.onDismissed != null)
config.onDismissed();
}
......
......@@ -123,7 +123,7 @@ class _RenderSlider extends RenderConstrainedBox {
double get _trackLength => size.width - 2.0 * _kReactionRadius;
Animated<double> _reaction;
Animation<double> _reaction;
AnimationController _reactionController;
HorizontalDragGestureRecognizer _drag;
......@@ -186,7 +186,7 @@ class _RenderSlider extends RenderConstrainedBox {
canvas.drawRect(new Rect.fromLTRB(trackLeft, trackTop, trackActive, trackBottom), primaryPaint);
Point activeLocation = new Point(trackActive, trackCenter);
if (_reaction.status != PerformanceStatus.dismissed) {
if (_reaction.status != AnimationStatus.dismissed) {
Paint reactionPaint = new Paint()..color = _activeColor.withAlpha(kRadialReactionAlpha);
canvas.drawCircle(activeLocation, _reaction.value, reactionPaint);
}
......
......@@ -65,7 +65,7 @@ class SnackBar extends StatelessComponent {
final Widget content;
final List<SnackBarAction> actions;
final Duration duration;
final Animated<double> animation;
final Animation<double> animation;
Widget build(BuildContext context) {
assert(animation != null);
......@@ -130,7 +130,7 @@ class SnackBar extends StatelessComponent {
);
}
SnackBar withAnimation(Animated<double> newAnimation, { Key fallbackKey }) {
SnackBar withAnimation(Animation<double> newAnimation, { Key fallbackKey }) {
return new SnackBar(
key: key ?? fallbackKey,
content: content,
......
......@@ -382,7 +382,7 @@ class _TabsScrollBehavior extends BoundedBehavior {
}
abstract class TabBarSelectionPerformanceListener {
void handleStatusChange(PerformanceStatus status);
void handleStatusChange(AnimationStatus status);
void handleProgressChange();
void handleSelectionDeactivate();
}
......@@ -415,7 +415,7 @@ class TabBarSelection<T> extends StatefulComponent {
class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
Animated<double> get animation => _controller.view;
Animation<double> get animation => _controller.view;
// Both the TabBar and TabBarView classes access _controller because they
// alternately drive selection progress between tabs.
final AnimationController _controller = new AnimationController(duration: _kTabBarScroll, value: 1.0);
......@@ -481,7 +481,7 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
// the previous and current selection index.
double value;
if (_controller.status == PerformanceStatus.completed)
if (_controller.status == AnimationStatus.completed)
value = 0.0;
else if (_previousValue == values.first)
value = _controller.value;
......@@ -584,11 +584,11 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
_selection = null;
}
void handleStatusChange(PerformanceStatus status) {
void handleStatusChange(AnimationStatus status) {
if (config.labels.length == 0)
return;
if (_valueIsChanging && status == PerformanceStatus.completed) {
if (_valueIsChanging && status == AnimationStatus.completed) {
_valueIsChanging = false;
_indicatorTween
..begin = _tabIndicatorRect(math.max(0, _selection.index - 1))
......@@ -868,7 +868,7 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
_updateScrollBehaviorForSelectedIndex(selectedIndex);
}
void handleStatusChange(PerformanceStatus status) {
void handleStatusChange(AnimationStatus status) {
}
void handleProgressChange() {
......@@ -876,14 +876,14 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
return;
// The TabBar is driving the TabBarSelection performance.
final Animated<double> animation = _selection.animation;
final Animation<double> animation = _selection.animation;
if (animation.status == PerformanceStatus.completed) {
if (animation.status == AnimationStatus.completed) {
_updateItemsAndScrollBehavior();
return;
}
if (animation.status != PerformanceStatus.forward)
if (animation.status != AnimationStatus.forward)
return;
final int selectedIndex = _selection.index;
......
......@@ -350,7 +350,7 @@ class _DialState extends State<_Dial> {
}
Tween<double> _thetaTween;
Animated<double> _theta;
Animation<double> _theta;
AnimationController _thetaController;
bool _dragging = false;
......
......@@ -99,15 +99,15 @@ abstract class RenderToggleable extends RenderConstrainedBox {
AnimationController get reactionController => _reactionController;
AnimationController _reactionController;
Animated<double> _reaction;
Animation<double> _reaction;
TapGestureRecognizer _tap;
void _handlePositionStateChanged(PerformanceStatus status) {
void _handlePositionStateChanged(AnimationStatus status) {
if (isInteractive) {
if (status == PerformanceStatus.completed && !_value)
if (status == AnimationStatus.completed && !_value)
onChanged(true);
else if (status == PerformanceStatus.dismissed && _value)
else if (status == AnimationStatus.dismissed && _value)
onChanged(false);
}
}
......
......@@ -78,14 +78,14 @@ class _TooltipState extends State<Tooltip> {
void initState() {
super.initState();
_controller = new AnimationController(duration: config.fadeDuration)
..addStatusListener((PerformanceStatus status) {
..addStatusListener((AnimationStatus status) {
switch (status) {
case PerformanceStatus.completed:
case AnimationStatus.completed:
assert(_entry != null);
assert(_timer == null);
resetShowTimer();
break;
case PerformanceStatus.dismissed:
case AnimationStatus.dismissed:
assert(_entry != null);
assert(_timer == null);
_entry.remove();
......@@ -117,7 +117,7 @@ class _TooltipState extends State<Tooltip> {
}
void resetShowTimer() {
assert(_controller.status == PerformanceStatus.completed);
assert(_controller.status == AnimationStatus.completed);
assert(_entry != null);
_timer = new Timer(config.showDuration, hideTooltip);
}
......@@ -149,7 +149,7 @@ class _TooltipState extends State<Tooltip> {
Overlay.of(context).insert(_entry);
}
_timer?.cancel();
if (_controller.status != PerformanceStatus.completed) {
if (_controller.status != AnimationStatus.completed) {
_timer = null;
_controller.forward();
} else {
......@@ -249,7 +249,7 @@ class _TooltipOverlay extends StatelessComponent {
final double borderRadius;
final double height;
final EdgeDims padding;
final Animated<double> animation;
final Animation<double> animation;
final Point target;
final double verticalOffset;
final EdgeDims screenEdgeMargin;
......
......@@ -854,9 +854,8 @@ abstract class RenderBoxContainerDefaultsMixin<ChildType extends RenderBox, Pare
}
}
class AnimatedFractionalOffsetValue extends AnimatedValue<FractionalOffset> {
AnimatedFractionalOffsetValue(FractionalOffset begin, { FractionalOffset end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
class FractionalOffsetTween extends Tween<FractionalOffset> {
FractionalOffsetTween({ FractionalOffset begin, FractionalOffset end }) : super(begin: begin, end: end);
FractionalOffset lerp(double t) => FractionalOffset.lerp(begin, end, t);
}
......@@ -73,8 +73,8 @@ class _DismissableState extends State<Dismissable> {
void initState() {
super.initState();
_dismissController = new AnimationController(duration: _kCardDismissDuration);
_dismissController.addStatusListener((PerformanceStatus status) {
if (status == PerformanceStatus.completed)
_dismissController.addStatusListener((AnimationStatus status) {
if (status == AnimationStatus.completed)
_handleDismissCompleted();
});
}
......@@ -251,9 +251,9 @@ class _DismissableState extends State<Dismissable> {
Widget build(BuildContext context) {
if (_resizeController != null) {
// make sure you remove this widget once it's been dismissed!
assert(_resizeController.status == PerformanceStatus.forward);
assert(_resizeController.status == AnimationStatus.forward);
Animated<double> squashAxisExtent = new Tween<double>(
Animation<double> squashAxisExtent = new Tween<double>(
begin: _directionIsYAxis ? _size.width : _size.height,
end: 0.0
).animate(new CurvedAnimation(
......
......@@ -30,32 +30,41 @@ class SmoothlyResizingOverflowBox extends StatefulComponent {
}
class _SmoothlyResizingOverflowBoxState extends State<SmoothlyResizingOverflowBox> {
ValuePerformance<Size> _size;
SizeTween _sizeTween;
CurveTween _curveTween;
Animation<Size> _size;
AnimationController _sizeController;
void initState() {
super.initState();
_size = new ValuePerformance(
variable: new AnimatedSizeValue(config.size, curve: config.curve),
duration: config.duration
)..addListener(() {
setState(() {});
});
_sizeController = new AnimationController(duration: config.duration);
_sizeTween = new SizeTween(begin: config.size);
_curveTween = new CurveTween(curve: config.curve);
_size = _sizeTween.chain(_curveTween).animate(_sizeController)
..addListener(() {
setState(() {});
});
}
void didUpdateConfig(SmoothlyResizingOverflowBox oldConfig) {
_size.duration = config.duration;
_size.variable.curve = config.curve;
bool needsAnimation = false;
if (config.size != oldConfig.size) {
AnimatedSizeValue variable = _size.variable;
variable.begin = variable.value;
variable.end = config.size;
_size.progress = 0.0;
_size.play();
_sizeTween
..begin = _size.value
..end = config.size;
needsAnimation = true;
}
_sizeController.duration = config.duration;
_curveTween.curve = config.curve;
if (needsAnimation) {
_sizeController
..value = 0.0
..forward();
}
}
void dispose() {
_size.stop();
_sizeController.stop();
super.dispose();
}
......@@ -91,9 +100,9 @@ class _Entry {
}
}
typedef Widget TransitionBuilderCallback(Animated<double> animation, Widget child);
typedef Widget TransitionBuilderCallback(Animation<double> animation, Widget child);
Widget _identityTransition(Animated<double> animation, Widget child) => child;
Widget _identityTransition(Animation<double> animation, Widget child) => child;
class EnterExitTransition extends StatefulComponent {
EnterExitTransition({
......
......@@ -73,7 +73,7 @@ class _HeroManifest {
abstract class HeroHandle {
bool get alwaysAnimate;
_HeroManifest _takeChild(Rect animationArea, Animated<double> currentAnimation);
_HeroManifest _takeChild(Rect animationArea, Animation<double> currentAnimation);
}
class Hero extends StatefulComponent {
......@@ -167,7 +167,7 @@ class HeroState extends State<Hero> implements HeroHandle {
bool get alwaysAnimate => config.alwaysAnimate;
_HeroManifest _takeChild(Rect animationArea, Animated<double> currentAnimation) {
_HeroManifest _takeChild(Rect animationArea, Animation<double> currentAnimation) {
assert(_mode == _HeroMode.measured || _mode == _HeroMode.taken);
final RenderBox renderObject = context.findRenderObject();
final Point heroTopLeft = renderObject.localToGlobal(Point.origin);
......@@ -263,7 +263,7 @@ class _HeroQuestState implements HeroHandle {
bool get taken => _taken;
bool _taken = false;
_HeroManifest _takeChild(Rect animationArea, Animated<double> currentAnimation) {
_HeroManifest _takeChild(Rect animationArea, Animation<double> currentAnimation) {
assert(!taken);
_taken = true;
Set<HeroState> states = sourceStates;
......@@ -278,7 +278,7 @@ class _HeroQuestState implements HeroHandle {
);
}
Widget build(BuildContext context, Animated<double> animation) {
Widget build(BuildContext context, Animation<double> animation) {
return new PositionedTransition(
rect: currentRect.animate(animation),
child: new RotationTransition(
......@@ -376,14 +376,14 @@ class HeroParty {
_heroes = _newHeroes;
}
Animated<double> _currentAnimation;
Animation<double> _currentAnimation;
void _clearCurrentAnimation() {
_currentAnimation?.removeStatusListener(_handleUpdate);
_currentAnimation = null;
}
void setAnimation(Animated<double> animation) {
void setAnimation(Animation<double> animation) {
assert(animation != null || _heroes.length == 0);
if (animation != _currentAnimation) {
_clearCurrentAnimation();
......@@ -392,9 +392,9 @@ class HeroParty {
}
}
void _handleUpdate(PerformanceStatus status) {
if (status == PerformanceStatus.completed ||
status == PerformanceStatus.dismissed) {
void _handleUpdate(AnimationStatus status) {
if (status == AnimationStatus.completed ||
status == AnimationStatus.dismissed) {
for (_HeroQuestState hero in _heroes) {
if (hero.targetState != null)
hero.targetState._setChild(hero.key);
......@@ -417,7 +417,7 @@ class HeroController extends NavigatorObserver {
}
HeroParty _party;
Animated<double> _animation;
Animation<double> _animation;
PageRoute _from;
PageRoute _to;
......@@ -452,7 +452,7 @@ class HeroController extends NavigatorObserver {
void _checkForHeroQuest() {
if (_from != null && _to != null && _from != _to) {
_to.offstage = _to.animation.status != PerformanceStatus.completed;
_to.offstage = _to.animation.status != AnimationStatus.completed;
Scheduler.instance.addPostFrameCallback(_updateQuest);
}
}
......@@ -505,9 +505,9 @@ class HeroController extends NavigatorObserver {
Map<Object, HeroHandle> heroesTo = Hero.of(_to.subtreeContext, mostValuableKeys);
_to.offstage = false;
Animated<double> animation = _animation;
Animation<double> animation = _animation;
Curve curve = Curves.ease;
if (animation.status == PerformanceStatus.reverse) {
if (animation.status == AnimationStatus.reverse) {
animation = new ReverseAnimation(animation);
curve = new Interval(animation.value, 1.0, curve: curve);
}
......
......@@ -84,8 +84,8 @@ typedef Tween<T> TweenVisitor<T>(Tween<T> tween, T targetValue, TweenConstructor
abstract class AnimatedWidgetBaseState<T extends AnimatedWidgetBase> extends State<T> {
AnimationController _controller;
Animated<double> get animation => _animation;
Animated<double> _animation;
Animation<double> get animation => _animation;
Animation<double> _animation;
void initState() {
super.initState();
......
......@@ -46,12 +46,12 @@ class ModalBarrier extends StatelessComponent {
class AnimatedModalBarrier extends AnimatedComponent {
AnimatedModalBarrier({
Key key,
Animated<Color> color,
Animation<Color> color,
this.dismissable: true
}) : color = color, super(key: key, animation: color);
/// If non-null, fill the barrier with this color.
final Animated<Color> color;
final Animation<Color> color;
/// Whether touching the barrier will pop the current route off the [Navigator].
final bool dismissable;
......
......@@ -92,8 +92,8 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
Duration get transitionDuration;
bool get opaque;
Animated<double> get animation => _animation;
Animated<double> _animation;
Animation<double> get animation => _animation;
Animation<double> _animation;
AnimationController _controller;
/// Called to create the animation controller that will drive the transitions to
......@@ -108,25 +108,25 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
/// Called to create the animation that exposes the current progress of
/// the transition controlled by the animation controller created by
/// [createAnimationController()].
Animated<double> createAnimation() {
Animation<double> createAnimation() {
assert(_controller != null);
return _controller.view;
}
T _result;
void handleStatusChanged(PerformanceStatus status) {
void handleStatusChanged(AnimationStatus status) {
switch (status) {
case PerformanceStatus.completed:
case AnimationStatus.completed:
if (overlayEntries.isNotEmpty)
overlayEntries.first.opaque = opaque;
break;
case PerformanceStatus.forward:
case PerformanceStatus.reverse:
case AnimationStatus.forward:
case AnimationStatus.reverse:
if (overlayEntries.isNotEmpty)
overlayEntries.first.opaque = false;
break;
case PerformanceStatus.dismissed:
case AnimationStatus.dismissed:
assert(!overlayEntries.first.opaque);
finished(); // clear the overlays
assert(overlayEntries.isEmpty);
......@@ -134,7 +134,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
}
}
Animated<double> get forwardAnimation => _forwardAnimation;
Animation<double> get forwardAnimation => _forwardAnimation;
final ProxyAnimation _forwardAnimation = new ProxyAnimation(kAlwaysDismissedAnimation);
void install(OverlayEntry insertionPoint) {
......@@ -177,7 +177,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
void _updateForwardAnimation(Route nextRoute) {
if (nextRoute is TransitionRoute && canTransitionTo(nextRoute) && nextRoute.canTransitionFrom(this)) {
Animated<double> current = _forwardAnimation.masterAnimation;
Animation<double> current = _forwardAnimation.masterAnimation;
if (current != null) {
if (current is TrainHoppingAnimation) {
TrainHoppingAnimation newAnimation;
......@@ -320,7 +320,7 @@ class _ModalScopeState extends State<_ModalScope> {
super.dispose();
}
void _animationStatusChanged(PerformanceStatus status) {
void _animationStatusChanged(AnimationStatus status) {
setState(() {
// The animation's states are our build state, and they changed already.
});
......@@ -342,7 +342,7 @@ class _ModalScopeState extends State<_ModalScope> {
contents = new Focus(
key: new GlobalObjectKey(config.route),
child: new IgnorePointer(
ignoring: config.route.animation?.status == PerformanceStatus.reverse,
ignoring: config.route.animation?.status == AnimationStatus.reverse,
child: config.route.buildTransitions(
context,
config.route.animation,
......@@ -396,8 +396,8 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
// The API for subclasses to override - used by _ModalScope
ModalPosition getPosition(BuildContext context) => null;
Widget buildPage(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation);
Widget buildTransitions(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation, Widget child) {
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation);
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation, Widget child) {
return child;
}
......@@ -442,7 +442,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
Widget barrier;
if (barrierColor != null) {
assert(barrierColor != _kTransparent);
Animated<Color> color = new ColorTween(
Animation<Color> color = new ColorTween(
begin: _kTransparent,
end: barrierColor
).animate(new CurvedAnimation(
......@@ -456,9 +456,9 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
} else {
barrier = new ModalBarrier(dismissable: barrierDismissable);
}
assert(animation.status != PerformanceStatus.dismissed);
assert(animation.status != AnimationStatus.dismissed);
return new IgnorePointer(
ignoring: animation.status == PerformanceStatus.reverse,
ignoring: animation.status == AnimationStatus.reverse,
child: barrier
);
}
......
......@@ -14,7 +14,7 @@ abstract class StatusTransitionComponent extends StatefulComponent {
assert(animation != null);
}
final Animated<double> animation;
final Animation<double> animation;
Widget build(BuildContext context);
......@@ -39,7 +39,7 @@ class _StatusTransitionState extends State<StatusTransitionComponent> {
super.dispose();
}
void _animationStatusChanged(PerformanceStatus status) {
void _animationStatusChanged(AnimationStatus status) {
setState(() {
// The animation's state is our build state, and it changed already.
});
......
......@@ -14,55 +14,6 @@ import 'framework.dart';
export 'package:flutter/animation.dart' show AnimationDirection;
export 'package:flutter/rendering.dart' show RelativeRect;
abstract class TransitionComponent extends StatefulComponent {
TransitionComponent({
Key key,
this.performance
}) : super(key: key) {
assert(performance != null);
}
final PerformanceView performance;
Widget build(BuildContext context);
_TransitionState createState() => new _TransitionState();
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('performance: $performance');
}
}
class _TransitionState extends State<TransitionComponent> {
void initState() {
super.initState();
config.performance.addListener(_performanceChanged);
}
void didUpdateConfig(TransitionComponent oldConfig) {
if (config.performance != oldConfig.performance) {
oldConfig.performance.removeListener(_performanceChanged);
config.performance.addListener(_performanceChanged);
}
}
void dispose() {
config.performance.removeListener(_performanceChanged);
super.dispose();
}
void _performanceChanged() {
setState(() {
// The performance's state is our build state, and it changed already.
});
}
Widget build(BuildContext context) {
return config.build(context);
}
}
abstract class AnimatedComponent extends StatefulComponent {
AnimatedComponent({
Key key,
......@@ -71,7 +22,7 @@ abstract class AnimatedComponent extends StatefulComponent {
assert(animation != null);
}
final Animated<Object> animation;
final Animation<Object> animation;
Widget build(BuildContext context);
......@@ -112,30 +63,15 @@ class _AnimatedComponentState extends State<AnimatedComponent> {
}
}
abstract class TransitionWithChild extends TransitionComponent {
TransitionWithChild({
Key key,
this.child,
PerformanceView performance
}) : super(key: key, performance: performance);
final Widget child;
Widget build(BuildContext context) => buildWithChild(context, child);
Widget buildWithChild(BuildContext context, Widget child);
}
class SlideTransition extends AnimatedComponent {
SlideTransition({
Key key,
Animated<FractionalOffset> position,
PerformanceView performance,
Animation<FractionalOffset> position,
this.transformHitTests: true,
this.child
}) : position = position, super(key: key, animation: position);
final Animated<FractionalOffset> position;
final Animation<FractionalOffset> position;
final bool transformHitTests;
final Widget child;
......@@ -151,12 +87,12 @@ class SlideTransition extends AnimatedComponent {
class ScaleTransition extends AnimatedComponent {
ScaleTransition({
Key key,
Animated<double> scale,
Animation<double> scale,
this.alignment: const FractionalOffset(0.5, 0.5),
this.child
}) : scale = scale, super(key: key, animation: scale);
final Animated<double> scale;
final Animation<double> scale;
final FractionalOffset alignment;
final Widget child;
......@@ -175,11 +111,11 @@ class ScaleTransition extends AnimatedComponent {
class RotationTransition extends AnimatedComponent {
RotationTransition({
Key key,
Animated<double> turns,
Animation<double> turns,
this.child
}) : turns = turns, super(key: key, animation: turns);
final Animated<double> turns;
final Animation<double> turns;
final Widget child;
Widget build(BuildContext context) {
......@@ -193,32 +129,14 @@ class RotationTransition extends AnimatedComponent {
}
}
class OldFadeTransition extends TransitionWithChild {
OldFadeTransition({
Key key,
this.opacity,
PerformanceView performance,
Widget child
}) : super(key: key,
performance: performance,
child: child);
final AnimatedValue<double> opacity;
Widget buildWithChild(BuildContext context, Widget child) {
performance.updateVariable(opacity);
return new Opacity(opacity: opacity.value, child: child);
}
}
class FadeTransition extends AnimatedComponent {
FadeTransition({
Key key,
Animated<double> opacity,
Animation<double> opacity,
this.child
}) : opacity = opacity, super(key: key, animation: opacity);
final Animated<double> opacity;
final Animation<double> opacity;
final Widget child;
Widget build(BuildContext context) {
......@@ -226,20 +144,17 @@ class FadeTransition extends AnimatedComponent {
}
}
class ColorTransition extends TransitionWithChild {
class ColorTransition extends AnimatedComponent {
ColorTransition({
Key key,
this.color,
PerformanceView performance,
Widget child
}) : super(key: key,
performance: performance,
child: child);
Animation<Color> color,
this.child
}) : color = color, super(key: key, animation: color);
final AnimatedColorValue color;
final Animation<Color> color;
final Widget child;
Widget buildWithChild(BuildContext context, Widget child) {
performance.updateVariable(color);
Widget build(BuildContext context) {
return new DecoratedBox(
decoration: new BoxDecoration(backgroundColor: color.value),
child: child
......@@ -247,61 +162,6 @@ class ColorTransition extends TransitionWithChild {
}
}
class SquashTransition extends TransitionWithChild {
SquashTransition({
Key key,
this.width,
this.height,
PerformanceView performance,
Widget child
}) : super(key: key,
performance: performance,
child: child);
final AnimatedValue<double> width;
final AnimatedValue<double> height;
Widget buildWithChild(BuildContext context, Widget child) {
if (width != null)
performance.updateVariable(width);
if (height != null)
performance.updateVariable(height);
return new SizedBox(width: width?.value, height: height?.value, child: child);
}
}
class AlignTransition extends TransitionWithChild {
AlignTransition({
Key key,
this.alignment,
this.widthFactor,
this.heightFactor,
PerformanceView performance,
Widget child
}) : super(key: key,
performance: performance,
child: child);
final AnimatedValue<FractionalOffset> alignment;
final AnimatedValue<double> widthFactor;
final AnimatedValue<double> heightFactor;
Widget buildWithChild(BuildContext context, Widget child) {
if (alignment != null)
performance.updateVariable(alignment);
if (widthFactor != null)
performance.updateVariable(widthFactor);
if (heightFactor != null)
performance.updateVariable(heightFactor);
return new Align(
alignment: alignment?.value,
widthFactor: widthFactor?.value,
heightFactor: heightFactor?.value,
child: child
);
}
}
/// An animated variable containing a RelativeRectangle
///
/// This class specializes the interpolation of AnimatedValue<RelativeRect> to
......@@ -323,13 +183,13 @@ class RelativeRectTween extends Tween<RelativeRect> {
class PositionedTransition extends AnimatedComponent {
PositionedTransition({
Key key,
Animated<RelativeRect> rect,
Animation<RelativeRect> rect,
this.child
}) : rect = rect, super(key: key, animation: rect) {
assert(rect != null);
}
final Animated<RelativeRect> rect;
final Animation<RelativeRect> rect;
final Widget child;
Widget build(BuildContext context) {
......@@ -343,31 +203,12 @@ class PositionedTransition extends AnimatedComponent {
}
}
class BuilderTransition extends TransitionComponent {
BuilderTransition({
Key key,
this.variables: const <AnimatedValue>[],
this.builder,
PerformanceView performance
}) : super(key: key,
performance: performance);
final List<AnimatedValue> variables;
final WidgetBuilder builder;
Widget build(BuildContext context) {
for (int i = 0; i < variables.length; ++i)
performance.updateVariable(variables[i]);
return builder(context);
}
}
typedef Widget TransitionBuilder(BuildContext context, Widget child);
class AnimatedBuilder extends AnimatedComponent {
AnimatedBuilder({
Key key,
Animated<Object> animation,
Animation<Object> animation,
this.builder,
this.child
}) : super(key: key, animation: animation);
......
......@@ -12,7 +12,7 @@ class TestTransition extends AnimatedComponent {
Key key,
this.childFirstHalf,
this.childSecondHalf,
Animated<double> animation
Animation<double> animation
}) : super(key: key, animation: animation) {
assert(animation != null);
}
......@@ -21,7 +21,7 @@ class TestTransition extends AnimatedComponent {
final Widget childSecondHalf;
Widget build(BuildContext context) {
final Animated<double> animation = this.animation;
final Animation<double> animation = this.animation;
if (animation.value >= 0.5)
return childSecondHalf;
return childFirstHalf;
......@@ -33,7 +33,7 @@ class TestRoute<T> extends PageRoute<T> {
final Widget child;
Duration get transitionDuration => kMaterialPageRouteTransitionDuration;
Color get barrierColor => null;
Widget buildPage(BuildContext context, Animated<double> animation, Animated<double> forwardAnimation) {
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
return 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