Commit 0b098ee2 authored by Adam Barth's avatar Adam Barth

Move Scaffold over to using AnimationController

Also, clean up the class hierarchy for AnimationController now that
we've renamed progress to value. That means everything in the hierarchy
now has a value, include Watchable. This patch renames Watchable to
Animated<T>, which lets us use that type almost everywhere.

I've added some ducktape to modal bottom sheets to avoid having to
refactor all of Navigator to use AnimationController. I'll remove the
ducktape in the next patch.
parent 386b2775
...@@ -12,9 +12,9 @@ class PageSelectorDemo extends StatelessComponent { ...@@ -12,9 +12,9 @@ class PageSelectorDemo extends StatelessComponent {
final ColorTween _previousColor = new ColorTween(begin: color, end: Colors.transparent); final ColorTween _previousColor = new ColorTween(begin: color, end: Colors.transparent);
final TabBarSelectionState selection = TabBarSelection.of(context); final TabBarSelectionState selection = TabBarSelection.of(context);
Animation animation = new CurvedAnimation(parent: selection.animation, curve: Curves.ease); CurvedAnimation animation = new CurvedAnimation(parent: selection.animation, curve: Curves.ease);
return new AnimationWatchingBuilder( return new AnimatedBuilder(
watchable: animation, animation: animation,
builder: (BuildContext context) { builder: (BuildContext context) {
Color background = selection.value == iconName ? _selectedColor.end : _selectedColor.begin; Color background = selection.value == iconName ? _selectedColor.end : _selectedColor.begin;
if (selection.valueIsChanging) { if (selection.valueIsChanging) {
......
...@@ -27,7 +27,7 @@ class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> { ...@@ -27,7 +27,7 @@ class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> {
}); });
} }
Animation animation; Animated<double> animation;
AnimationController controller; AnimationController controller;
void handleTap() { void handleTap() {
...@@ -55,19 +55,19 @@ class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> { ...@@ -55,19 +55,19 @@ class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> {
), ),
new LinearProgressIndicator(), new LinearProgressIndicator(),
new LinearProgressIndicator(), new LinearProgressIndicator(),
new LinearProgressIndicator(value: animation.progress), new LinearProgressIndicator(value: animation.value),
new CircularProgressIndicator(), new CircularProgressIndicator(),
new SizedBox( new SizedBox(
width: 20.0, width: 20.0,
height: 20.0, height: 20.0,
child: new CircularProgressIndicator(value: animation.progress) child: new CircularProgressIndicator(value: animation.value)
), ),
new SizedBox( new SizedBox(
width: 50.0, width: 50.0,
height: 30.0, height: 30.0,
child: new CircularProgressIndicator(value: animation.progress) child: new CircularProgressIndicator(value: animation.value)
), ),
new Text("${(animation.progress * 100.0).toStringAsFixed(1)}%" + (controller.isAnimating ? '' : ' (paused)')) new Text("${(animation.value * 100.0).toStringAsFixed(1)}%" + (controller.isAnimating ? '' : ' (paused)'))
]; ];
return new Column( return new Column(
children: indicators children: indicators
...@@ -87,8 +87,8 @@ class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> { ...@@ -87,8 +87,8 @@ class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> {
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: new Container( child: new Container(
padding: const EdgeDims.symmetric(vertical: 12.0, horizontal: 8.0), padding: const EdgeDims.symmetric(vertical: 12.0, horizontal: 8.0),
child: new AnimationWatchingBuilder( child: new AnimatedBuilder(
watchable: animation, animation: animation,
builder: buildIndicators builder: buildIndicators
) )
) )
......
...@@ -33,14 +33,14 @@ class CardTransition extends StatelessComponent { ...@@ -33,14 +33,14 @@ class CardTransition extends StatelessComponent {
}); });
final Widget child; final Widget child;
final Animation animation; final Animated<double> animation;
final Evaluatable<double> x; final Evaluatable<double> x;
final Evaluatable<double> opacity; final Evaluatable<double> opacity;
final Evaluatable<double> scale; final Evaluatable<double> scale;
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new AnimationWatchingBuilder( return new AnimatedBuilder(
watchable: animation, animation: animation,
builder: (BuildContext context) { builder: (BuildContext context) {
double currentScale = scale.evaluate(animation); double currentScale = scale.evaluate(animation);
Matrix4 transform = new Matrix4.identity() Matrix4 transform = new Matrix4.identity()
...@@ -62,7 +62,7 @@ class SmoothBlockState extends State<SmoothBlock> { ...@@ -62,7 +62,7 @@ class SmoothBlockState extends State<SmoothBlock> {
double _height = 100.0; double _height = 100.0;
Widget _handleEnter(Animation animation, Widget child) { Widget _handleEnter(Animated<double> animation, Widget child) {
return new CardTransition( return new CardTransition(
x: new Tween<double>(begin: -200.0, end: 0.0), x: new Tween<double>(begin: -200.0, end: 0.0),
opacity: new Tween<double>(begin: 0.0, end: 1.0), opacity: new Tween<double>(begin: 0.0, end: 1.0),
...@@ -72,7 +72,7 @@ class SmoothBlockState extends State<SmoothBlock> { ...@@ -72,7 +72,7 @@ class SmoothBlockState extends State<SmoothBlock> {
); );
} }
Widget _handleExit(Animation animation, Widget child) { Widget _handleExit(Animated<double> animation, Widget child) {
return new CardTransition( return new CardTransition(
x: new Tween<double>(begin: 0.0, end: 200.0), x: new Tween<double>(begin: 0.0, end: 200.0),
opacity: new Tween<double>(begin: 1.0, end: 0.0), opacity: new Tween<double>(begin: 1.0, end: 0.0),
......
...@@ -13,16 +13,16 @@ import 'forces.dart'; ...@@ -13,16 +13,16 @@ import 'forces.dart';
import 'listener_helpers.dart'; import 'listener_helpers.dart';
import 'simulation_stepper.dart'; import 'simulation_stepper.dart';
abstract class Watchable { abstract class Animated<T> {
const Watchable(); const Animated();
/// Calls the listener every time the progress of the performance changes. /// Calls the listener every time the value of the animation changes.
void addListener(VoidCallback listener); void addListener(VoidCallback listener);
/// Stop calling the listener every time the progress of the performance changes. /// Stop calling the listener every time the value of the animation changes.
void removeListener(VoidCallback listener); void removeListener(VoidCallback listener);
/// Calls listener every time the status of the performance changes. /// Calls listener every time the status of the animation changes.
void addStatusListener(PerformanceStatusListener listener); void addStatusListener(PerformanceStatusListener listener);
/// Stops calling the listener every time the status of the performance changes. /// Stops calling the listener every time the status of the animation changes.
void removeStatusListener(PerformanceStatusListener listener); void removeStatusListener(PerformanceStatusListener listener);
/// The current status of this animation. /// The current status of this animation.
...@@ -31,6 +31,9 @@ abstract class Watchable { ...@@ -31,6 +31,9 @@ abstract class Watchable {
/// The current direction of the animation. /// The current direction of the animation.
AnimationDirection get direction; AnimationDirection get direction;
/// The current value of the animation.
T get value;
/// Whether this animation is stopped at the beginning. /// Whether this animation is stopped at the beginning.
bool get isDismissed => status == PerformanceStatus.dismissed; bool get isDismissed => status == PerformanceStatus.dismissed;
...@@ -77,8 +80,8 @@ abstract class Watchable { ...@@ -77,8 +80,8 @@ abstract class Watchable {
} }
} }
abstract class ProxyWatchableMixin implements Watchable { abstract class ProxyAnimatedMixin {
Watchable get parent; Animated<double> get parent;
void addListener(VoidCallback listener) => parent.addListener(listener); void addListener(VoidCallback listener) => parent.addListener(listener);
void removeListener(VoidCallback listener) => parent.removeListener(listener); void removeListener(VoidCallback listener) => parent.removeListener(listener);
...@@ -92,37 +95,30 @@ abstract class ProxyWatchableMixin implements Watchable { ...@@ -92,37 +95,30 @@ abstract class ProxyWatchableMixin implements Watchable {
abstract class Evaluatable<T> { abstract class Evaluatable<T> {
const Evaluatable(); const Evaluatable();
T evaluate(Animation animation); T evaluate(Animated<double> animation);
WatchableValue<T> watch(Animation parent) { Animated<T> watch(Animated<double> parent) {
return new WatchableValue<T>(parent: parent, evaluatable: this); return new _AnimatedEvaluation<T>(parent, this);
} }
} }
class WatchableValue<T> extends Watchable with ProxyWatchableMixin { class _AnimatedEvaluation<T> extends Animated<T> with ProxyAnimatedMixin {
WatchableValue({ this.parent, this.evaluatable }); _AnimatedEvaluation(this.parent, this._evaluatable);
final Animation parent;
final Evaluatable<T> evaluatable;
T get value => evaluatable.evaluate(parent); /// The animation from which this value is derived.
} final Animated<double> parent;
abstract class Animation extends Watchable { final Evaluatable<T> _evaluatable;
/// The current progress of this animation (a value from 0.0 to 1.0).
double get progress;
String toStringDetails() { T get value => _evaluatable.evaluate(parent);
return '${super.toStringDetails()} ${progress.toStringAsFixed(3)}';
}
} }
class AnimationController extends Animation class AnimationController extends Animated<double>
with EagerListenerMixin, LocalPerformanceListenersMixin, LocalPerformanceStatusListenersMixin { with EagerListenerMixin, LocalPerformanceListenersMixin, LocalPerformanceStatusListenersMixin {
AnimationController({ this.duration, double progress, this.debugLabel }) { AnimationController({ this.duration, double value, this.debugLabel }) {
_timeline = new SimulationStepper(_tick); _timeline = new SimulationStepper(_tick);
if (progress != null) if (value != null)
_timeline.value = progress.clamp(0.0, 1.0); _timeline.value = value.clamp(0.0, 1.0);
} }
/// A label that is used in the [toString] output. Intended to aid with /// A label that is used in the [toString] output. Intended to aid with
...@@ -132,7 +128,7 @@ class AnimationController extends Animation ...@@ -132,7 +128,7 @@ class AnimationController extends Animation
/// Returns a [Animation] for this performance, /// Returns a [Animation] for this performance,
/// so that a pointer to this object can be passed around without /// so that a pointer to this object can be passed around without
/// allowing users of that pointer to mutate the Performance state. /// allowing users of that pointer to mutate the Performance state.
Animation get view => this; Animated<double> get view => this;
/// The length of time this performance should last. /// The length of time this performance should last.
Duration duration; Duration duration;
...@@ -144,8 +140,8 @@ class AnimationController extends Animation ...@@ -144,8 +140,8 @@ class AnimationController extends Animation
/// The progress of this performance along the timeline. /// The progress of this performance along the timeline.
/// ///
/// Note: Setting this value stops the current animation. /// Note: Setting this value stops the current animation.
double get progress => _timeline.value.clamp(0.0, 1.0); double get value => _timeline.value.clamp(0.0, 1.0);
void set progress(double t) { void set value(double t) {
stop(); stop();
_timeline.value = t.clamp(0.0, 1.0); _timeline.value = t.clamp(0.0, 1.0);
_checkStatusChanged(); _checkStatusChanged();
...@@ -155,9 +151,9 @@ class AnimationController extends Animation ...@@ -155,9 +151,9 @@ class AnimationController extends Animation
bool get isAnimating => _timeline.isAnimating; bool get isAnimating => _timeline.isAnimating;
PerformanceStatus get status { PerformanceStatus get status {
if (!isAnimating && progress == 1.0) if (!isAnimating && value == 1.0)
return PerformanceStatus.completed; return PerformanceStatus.completed;
if (!isAnimating && progress == 0.0) if (!isAnimating && value == 0.0)
return PerformanceStatus.dismissed; return PerformanceStatus.dismissed;
return _direction == AnimationDirection.forward ? return _direction == AnimationDirection.forward ?
PerformanceStatus.forward : PerformanceStatus.forward :
...@@ -200,7 +196,7 @@ class AnimationController extends Animation ...@@ -200,7 +196,7 @@ class AnimationController extends Animation
Future fling({double velocity: 1.0, Force force}) { Future fling({double velocity: 1.0, Force force}) {
force ??= kDefaultSpringForce; force ??= kDefaultSpringForce;
_direction = velocity < 0.0 ? AnimationDirection.reverse : AnimationDirection.forward; _direction = velocity < 0.0 ? AnimationDirection.reverse : AnimationDirection.forward;
return _timeline.animateWith(force.release(progress, velocity)); return _timeline.animateWith(force.release(value, velocity));
} }
/// Starts running this animation in the forward direction, and /// Starts running this animation in the forward direction, and
...@@ -234,7 +230,7 @@ class AnimationController extends Animation ...@@ -234,7 +230,7 @@ class AnimationController extends Animation
String toStringDetails() { String toStringDetails() {
String paused = _timeline.isAnimating ? '' : '; paused'; String paused = _timeline.isAnimating ? '' : '; paused';
String label = debugLabel == null ? '' : '; for $debugLabel'; String label = debugLabel == null ? '' : '; for $debugLabel';
String more = super.toStringDetails(); String more = '${super.toStringDetails()} ${value.toStringAsFixed(3)}';
return '$more$paused$label'; return '$more$paused$label';
} }
} }
...@@ -261,14 +257,14 @@ class _RepeatingSimulation extends Simulation { ...@@ -261,14 +257,14 @@ class _RepeatingSimulation extends Simulation {
bool isDone(double timeInSeconds) => false; bool isDone(double timeInSeconds) => false;
} }
class CurvedAnimation extends Animation with ProxyWatchableMixin { class CurvedAnimation extends Animated<double> with ProxyAnimatedMixin {
CurvedAnimation({ this.parent, this.curve, this.reverseCurve }) { CurvedAnimation({ this.parent, this.curve, this.reverseCurve }) {
assert(parent != null); assert(parent != null);
assert(curve != null); assert(curve != null);
parent.addStatusListener(_handleStatusChanged); parent.addStatusListener(_handleStatusChanged);
} }
final Animation parent; final Animated<double> parent;
/// The curve to use in the forward direction. /// The curve to use in the forward direction.
Curve curve; Curve curve;
...@@ -300,11 +296,11 @@ class CurvedAnimation extends Animation with ProxyWatchableMixin { ...@@ -300,11 +296,11 @@ class CurvedAnimation extends Animation with ProxyWatchableMixin {
} }
} }
double get progress { double get value {
final bool useForwardCurve = reverseCurve == null || (_curveDirection ?? parent.direction) == AnimationDirection.forward; final bool useForwardCurve = reverseCurve == null || (_curveDirection ?? parent.direction) == AnimationDirection.forward;
Curve activeCurve = useForwardCurve ? curve : reverseCurve; Curve activeCurve = useForwardCurve ? curve : reverseCurve;
double t = parent.progress; double t = parent.value;
if (activeCurve == null) if (activeCurve == null)
return t; return t;
if (t == 0.0 || t == 1.0) { if (t == 0.0 || t == 1.0) {
...@@ -327,10 +323,10 @@ class Tween<T extends dynamic> extends Evaluatable<T> { ...@@ -327,10 +323,10 @@ class Tween<T extends dynamic> extends Evaluatable<T> {
/// Returns the value this variable has at the given animation clock value. /// Returns the value this variable has at the given animation clock value.
T lerp(double t) => begin + (end - begin) * t; T lerp(double t) => begin + (end - begin) * t;
T evaluate(Animation animation) { T evaluate(Animated<double> animation) {
if (end == null) if (end == null)
return begin; return begin;
double t = animation.progress; double t = animation.value;
if (t == 0.0) if (t == 0.0)
return begin; return begin;
if (t == 1.0) if (t == 1.0)
......
...@@ -21,24 +21,24 @@ const Color _kBarrierColor = Colors.black54; ...@@ -21,24 +21,24 @@ const Color _kBarrierColor = Colors.black54;
class BottomSheet extends StatefulComponent { class BottomSheet extends StatefulComponent {
BottomSheet({ BottomSheet({
Key key, Key key,
this.performance, this.animationController,
this.onClosing, this.onClosing,
this.builder this.builder
}) : super(key: key) { }) : super(key: key) {
assert(onClosing != null); assert(onClosing != null);
} }
/// The performance that controls the bottom sheet's position. The BottomSheet /// The animation that controls the bottom sheet's position. The BottomSheet
/// widget will manipulate the position of this performance, it is not just a /// widget will manipulate the position of this animation, it is not just a
/// passive observer. /// passive observer.
final Performance performance; final AnimationController animationController;
final VoidCallback onClosing; final VoidCallback onClosing;
final WidgetBuilder builder; final WidgetBuilder builder;
_BottomSheetState createState() => new _BottomSheetState(); _BottomSheetState createState() => new _BottomSheetState();
static Performance createPerformanceController() { static AnimationController createAnimationController() {
return new Performance( return new AnimationController(
duration: _kBottomSheetDuration, duration: _kBottomSheetDuration,
debugLabel: 'BottomSheet' debugLabel: 'BottomSheet'
); );
...@@ -54,12 +54,12 @@ class _BottomSheetState extends State<BottomSheet> { ...@@ -54,12 +54,12 @@ class _BottomSheetState extends State<BottomSheet> {
return renderBox.size.height; return renderBox.size.height;
} }
bool get _dismissUnderway => config.performance.direction == AnimationDirection.reverse; bool get _dismissUnderway => config.animationController.direction == AnimationDirection.reverse;
void _handleDragUpdate(double delta) { void _handleDragUpdate(double delta) {
if (_dismissUnderway) if (_dismissUnderway)
return; return;
config.performance.progress -= delta / (_childHeight ?? delta); config.animationController.value -= delta / (_childHeight ?? delta);
} }
void _handleDragEnd(Offset velocity) { void _handleDragEnd(Offset velocity) {
...@@ -67,14 +67,14 @@ class _BottomSheetState extends State<BottomSheet> { ...@@ -67,14 +67,14 @@ class _BottomSheetState extends State<BottomSheet> {
return; return;
if (velocity.dy > _kMinFlingVelocity) { if (velocity.dy > _kMinFlingVelocity) {
double flingVelocity = -velocity.dy / _childHeight; double flingVelocity = -velocity.dy / _childHeight;
config.performance.fling(velocity: flingVelocity); config.animationController.fling(velocity: flingVelocity);
if (flingVelocity < 0.0) if (flingVelocity < 0.0)
config.onClosing(); config.onClosing();
} else if (config.performance.progress < _kCloseProgressThreshold) { } else if (config.animationController.value < _kCloseProgressThreshold) {
config.performance.fling(velocity: -1.0); config.animationController.fling(velocity: -1.0);
config.onClosing(); config.onClosing();
} else { } else {
config.performance.forward(); config.animationController.forward();
} }
} }
...@@ -129,17 +129,41 @@ class _ModalBottomSheet extends StatefulComponent { ...@@ -129,17 +129,41 @@ class _ModalBottomSheet extends StatefulComponent {
} }
class _ModalBottomSheetState extends State<_ModalBottomSheet> { class _ModalBottomSheetState extends State<_ModalBottomSheet> {
// TODO(abarth): Delete _controllerPerformanceAdaptor when navigator uses
// AnimationController and friends.
AnimationController _controllerPerformanceAdaptor;
void initState() {
super.initState();
_controllerPerformanceAdaptor = new AnimationController();
_updateControllerPerformanceAdaptor();
}
void didUpdateConfig(_ModalBottomSheet oldConfig) {
if (config.route.performance != oldConfig.route.performance)
_updateControllerPerformanceAdaptor();
}
void _updateControllerPerformanceAdaptor() {
Performance performance = config.route.performance;
_controllerPerformanceAdaptor
..duration = performance.duration
..value = performance.progress;
if (performance.isAnimating)
_controllerPerformanceAdaptor.play(performance.direction);
}
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new GestureDetector( return new GestureDetector(
onTap: () => Navigator.pop(context), onTap: () => Navigator.pop(context),
child: new BuilderTransition( child: new AnimatedBuilder(
performance: config.route.performance, animation: _controllerPerformanceAdaptor,
builder: (BuildContext context) { builder: (BuildContext context) {
return new ClipRect( return new ClipRect(
child: new CustomOneChildLayout( child: new CustomOneChildLayout(
delegate: new _ModalBottomSheetLayout(config.route.performance.progress), delegate: new _ModalBottomSheetLayout(config.route.performance.progress),
child: new BottomSheet( child: new BottomSheet(
performance: config.route.performance, animationController: _controllerPerformanceAdaptor,
onClosing: () => Navigator.pop(context), onClosing: () => Navigator.pop(context),
builder: config.route.builder builder: config.route.builder
) )
...@@ -163,8 +187,8 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> { ...@@ -163,8 +187,8 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
bool get barrierDismissable => true; bool get barrierDismissable => true;
Color get barrierColor => Colors.black54; Color get barrierColor => Colors.black54;
Performance createPerformanceController() { AnimationController createAnimationController() {
return BottomSheet.createPerformanceController(); return BottomSheet.createAnimationController();
} }
Widget buildPage(BuildContext context, PerformanceView performance, PerformanceView forwardPerformance) { Widget buildPage(BuildContext context, PerformanceView performance, PerformanceView forwardPerformance) {
......
...@@ -133,7 +133,7 @@ class _DialogRoute<T> extends PopupRoute<T> { ...@@ -133,7 +133,7 @@ class _DialogRoute<T> extends PopupRoute<T> {
} }
Widget buildTransitions(BuildContext context, PerformanceView performance, PerformanceView forwardPerformance, Widget child) { Widget buildTransitions(BuildContext context, PerformanceView performance, PerformanceView forwardPerformance, Widget child) {
return new FadeTransition( return new OldFadeTransition(
performance: performance, performance: performance,
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: Curves.easeOut), opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: Curves.easeOut),
child: child child: child
......
...@@ -87,7 +87,7 @@ class _DropDownMenu<T> extends StatusTransitionComponent { ...@@ -87,7 +87,7 @@ class _DropDownMenu<T> extends StatusTransitionComponent {
final double end = (start + 1.5 * unit).clamp(0.0, 1.0); final double end = (start + 1.5 * unit).clamp(0.0, 1.0);
opacity = new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(start, end), reverseCurve: const Interval(0.75, 1.0)); opacity = new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(start, end), reverseCurve: const Interval(0.75, 1.0));
} }
children.add(new FadeTransition( children.add(new OldFadeTransition(
performance: route.performance, performance: route.performance,
opacity: opacity, opacity: opacity,
child: new InkWell( child: new InkWell(
...@@ -120,7 +120,7 @@ class _DropDownMenu<T> extends StatusTransitionComponent { ...@@ -120,7 +120,7 @@ class _DropDownMenu<T> extends StatusTransitionComponent {
reverseCurve: const Interval(0.0, 0.001) reverseCurve: const Interval(0.0, 0.001)
); );
return new FadeTransition( return new OldFadeTransition(
performance: route.performance, performance: route.performance,
opacity: menuOpacity, opacity: menuOpacity,
child: new BuilderTransition( child: new BuilderTransition(
......
...@@ -61,7 +61,7 @@ class _PopupMenu<T> extends StatelessComponent { ...@@ -61,7 +61,7 @@ class _PopupMenu<T> extends StatelessComponent {
for (int i = 0; i < route.items.length; ++i) { for (int i = 0; i < route.items.length; ++i) {
double start = (i + 1) * unit; double start = (i + 1) * unit;
double end = (start + 1.5 * unit).clamp(0.0, 1.0); double end = (start + 1.5 * unit).clamp(0.0, 1.0);
children.add(new FadeTransition( children.add(new OldFadeTransition(
performance: route.performance, performance: route.performance,
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(start, end)), opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(start, end)),
child: new InkWell( child: new InkWell(
......
...@@ -27,7 +27,7 @@ abstract class ProgressIndicator extends StatefulComponent { ...@@ -27,7 +27,7 @@ abstract class ProgressIndicator extends StatefulComponent {
Color _getBackgroundColor(BuildContext context) => Theme.of(context).primarySwatch[200]; Color _getBackgroundColor(BuildContext context) => Theme.of(context).primarySwatch[200];
Color _getValueColor(BuildContext context) => Theme.of(context).primaryColor; Color _getValueColor(BuildContext context) => Theme.of(context).primaryColor;
Widget _buildIndicator(BuildContext context, double performanceValue); Widget _buildIndicator(BuildContext context, double animationValue);
_ProgressIndicatorState createState() => new _ProgressIndicatorState(); _ProgressIndicatorState createState() => new _ProgressIndicatorState();
...@@ -38,36 +38,33 @@ abstract class ProgressIndicator extends StatefulComponent { ...@@ -38,36 +38,33 @@ abstract class ProgressIndicator extends StatefulComponent {
} }
class _ProgressIndicatorState extends State<ProgressIndicator> { class _ProgressIndicatorState extends State<ProgressIndicator> {
Animated<double> _animation;
ValuePerformance<double> _performance; AnimationController _controller;
void initState() { void initState() {
super.initState(); super.initState();
_performance = new ValuePerformance<double>( _controller = new AnimationController(
variable: new AnimatedValue<double>(0.0, end: 1.0, curve: Curves.ease),
duration: const Duration(milliseconds: 1500) duration: const Duration(milliseconds: 1500)
); )..addStatusListener((PerformanceStatus status) {
_performance.addStatusListener((PerformanceStatus status) {
if (status == PerformanceStatus.completed) if (status == PerformanceStatus.completed)
_restartAnimation(); _restartAnimation();
}); })..forward();
_performance.play(); _animation = new CurvedAnimation(parent: _controller, curve: Curves.ease);
} }
void _restartAnimation() { void _restartAnimation() {
_performance.progress = 0.0; _controller.value = 0.0;
_performance.play(); _controller.forward();
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (config.value != null) if (config.value != null)
return config._buildIndicator(context, _performance.value); return config._buildIndicator(context, _animation.value);
return new BuilderTransition( return new AnimatedBuilder(
variables: <AnimatedValue<double>>[_performance.variable], animation: _animation,
performance: _performance.view,
builder: (BuildContext context) { builder: (BuildContext context) {
return config._buildIndicator(context, _performance.value); return config._buildIndicator(context, _animation.value);
} }
); );
} }
...@@ -78,13 +75,13 @@ class _LinearProgressIndicatorPainter extends CustomPainter { ...@@ -78,13 +75,13 @@ class _LinearProgressIndicatorPainter extends CustomPainter {
this.backgroundColor, this.backgroundColor,
this.valueColor, this.valueColor,
this.value, this.value,
this.performanceValue this.animationValue
}); });
final Color backgroundColor; final Color backgroundColor;
final Color valueColor; final Color valueColor;
final double value; final double value;
final double performanceValue; final double animationValue;
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
Paint paint = new Paint() Paint paint = new Paint()
...@@ -97,7 +94,7 @@ class _LinearProgressIndicatorPainter extends CustomPainter { ...@@ -97,7 +94,7 @@ class _LinearProgressIndicatorPainter extends CustomPainter {
double width = value.clamp(0.0, 1.0) * size.width; double width = value.clamp(0.0, 1.0) * size.width;
canvas.drawRect(Point.origin & new Size(width, size.height), paint); canvas.drawRect(Point.origin & new Size(width, size.height), paint);
} else { } else {
double startX = size.width * (1.5 * performanceValue - 0.5); double startX = size.width * (1.5 * animationValue - 0.5);
double endX = startX + 0.5 * size.width; double endX = startX + 0.5 * size.width;
double x = startX.clamp(0.0, size.width); double x = startX.clamp(0.0, size.width);
double width = endX.clamp(0.0, size.width) - x; double width = endX.clamp(0.0, size.width) - x;
...@@ -109,7 +106,7 @@ class _LinearProgressIndicatorPainter extends CustomPainter { ...@@ -109,7 +106,7 @@ class _LinearProgressIndicatorPainter extends CustomPainter {
return oldPainter.backgroundColor != backgroundColor return oldPainter.backgroundColor != backgroundColor
|| oldPainter.valueColor != valueColor || oldPainter.valueColor != valueColor
|| oldPainter.value != value || oldPainter.value != value
|| oldPainter.performanceValue != performanceValue; || oldPainter.animationValue != animationValue;
} }
} }
...@@ -119,7 +116,7 @@ class LinearProgressIndicator extends ProgressIndicator { ...@@ -119,7 +116,7 @@ class LinearProgressIndicator extends ProgressIndicator {
double value double value
}) : super(key: key, value: value); }) : super(key: key, value: value);
Widget _buildIndicator(BuildContext context, double performanceValue) { Widget _buildIndicator(BuildContext context, double animationValue) {
return new Container( return new Container(
constraints: new BoxConstraints.tightFor( constraints: new BoxConstraints.tightFor(
width: double.INFINITY, width: double.INFINITY,
...@@ -130,7 +127,7 @@ class LinearProgressIndicator extends ProgressIndicator { ...@@ -130,7 +127,7 @@ class LinearProgressIndicator extends ProgressIndicator {
backgroundColor: _getBackgroundColor(context), backgroundColor: _getBackgroundColor(context),
valueColor: _getValueColor(context), valueColor: _getValueColor(context),
value: value, value: value,
performanceValue: performanceValue animationValue: animationValue
) )
) )
); );
...@@ -147,12 +144,12 @@ class _CircularProgressIndicatorPainter extends CustomPainter { ...@@ -147,12 +144,12 @@ class _CircularProgressIndicatorPainter extends CustomPainter {
const _CircularProgressIndicatorPainter({ const _CircularProgressIndicatorPainter({
this.valueColor, this.valueColor,
this.value, this.value,
this.performanceValue this.animationValue
}); });
final Color valueColor; final Color valueColor;
final double value; final double value;
final double performanceValue; final double animationValue;
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
Paint paint = new Paint() Paint paint = new Paint()
...@@ -166,7 +163,7 @@ class _CircularProgressIndicatorPainter extends CustomPainter { ...@@ -166,7 +163,7 @@ class _CircularProgressIndicatorPainter extends CustomPainter {
..arcTo(Point.origin & size, _kStartAngle, angle, false); ..arcTo(Point.origin & size, _kStartAngle, angle, false);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
} else { } else {
double startAngle = _kTwoPI * (1.75 * performanceValue - 0.75); double startAngle = _kTwoPI * (1.75 * animationValue - 0.75);
double endAngle = startAngle + _kTwoPI * 0.75; double endAngle = startAngle + _kTwoPI * 0.75;
double arcAngle = startAngle.clamp(0.0, _kTwoPI); double arcAngle = startAngle.clamp(0.0, _kTwoPI);
double arcSweep = endAngle.clamp(0.0, _kTwoPI) - arcAngle; double arcSweep = endAngle.clamp(0.0, _kTwoPI) - arcAngle;
...@@ -179,7 +176,7 @@ class _CircularProgressIndicatorPainter extends CustomPainter { ...@@ -179,7 +176,7 @@ class _CircularProgressIndicatorPainter extends CustomPainter {
bool shouldRepaint(_CircularProgressIndicatorPainter oldPainter) { bool shouldRepaint(_CircularProgressIndicatorPainter oldPainter) {
return oldPainter.valueColor != valueColor return oldPainter.valueColor != valueColor
|| oldPainter.value != value || oldPainter.value != value
|| oldPainter.performanceValue != performanceValue; || oldPainter.animationValue != animationValue;
} }
} }
...@@ -189,7 +186,7 @@ class CircularProgressIndicator extends ProgressIndicator { ...@@ -189,7 +186,7 @@ class CircularProgressIndicator extends ProgressIndicator {
double value double value
}) : super(key: key, value: value); }) : super(key: key, value: value);
Widget _buildIndicator(BuildContext context, double performanceValue) { Widget _buildIndicator(BuildContext context, double animationValue) {
return new Container( return new Container(
constraints: new BoxConstraints( constraints: new BoxConstraints(
minWidth: _kMinCircularProgressIndicatorSize, minWidth: _kMinCircularProgressIndicatorSize,
...@@ -199,7 +196,7 @@ class CircularProgressIndicator extends ProgressIndicator { ...@@ -199,7 +196,7 @@ class CircularProgressIndicator extends ProgressIndicator {
painter: new _CircularProgressIndicatorPainter( painter: new _CircularProgressIndicatorPainter(
valueColor: _getValueColor(context), valueColor: _getValueColor(context),
value: value, value: value,
performanceValue: performanceValue animationValue: animationValue
) )
) )
); );
......
...@@ -111,18 +111,18 @@ class _FloatingActionButtonTransition extends StatefulComponent { ...@@ -111,18 +111,18 @@ class _FloatingActionButtonTransition extends StatefulComponent {
} }
class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTransition> { class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTransition> {
final Performance performance = new Performance(duration: _kFloatingActionButtonSegue); final AnimationController controller = new AnimationController(duration: _kFloatingActionButtonSegue);
Widget oldChild; Widget oldChild;
void initState() { void initState() {
super.initState(); super.initState();
performance.play().then((_) { controller.forward().then((_) {
oldChild = null; oldChild = null;
}); });
} }
void dispose() { void dispose() {
performance.stop(); controller.stop();
super.dispose(); super.dispose();
} }
...@@ -130,9 +130,9 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr ...@@ -130,9 +130,9 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
if (Widget.canUpdate(oldConfig.child, config.child)) if (Widget.canUpdate(oldConfig.child, config.child))
return; return;
oldChild = oldConfig.child; oldChild = oldConfig.child;
performance controller
..progress = 0.0 ..value = 0.0
..play().then((_) { ..forward().then((_) {
oldChild = null; oldChild = null;
}); });
} }
...@@ -141,15 +141,23 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr ...@@ -141,15 +141,23 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
final List<Widget> children = new List<Widget>(); final List<Widget> children = new List<Widget>();
if (oldChild != null) { if (oldChild != null) {
children.add(new ScaleTransition( children.add(new ScaleTransition(
scale: new AnimatedValue<double>(1.0, end: 0.0, curve: new Interval(0.0, 0.5, curve: Curves.easeIn)), // TODO(abarth): We should use ReversedAnimation here.
performance: performance, scale: new Tween<double>(
begin: 1.0,
end: 0.0
).watch(new CurvedAnimation(
parent: controller,
curve: const Interval(0.0, 0.5, curve: Curves.easeIn)
)),
child: oldChild child: oldChild
)); ));
} }
children.add(new ScaleTransition( children.add(new ScaleTransition(
scale: new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(0.5, 1.0, curve: Curves.easeIn)), scale: new CurvedAnimation(
performance: performance, parent: controller,
curve: const Interval(0.5, 1.0, curve: Curves.easeIn)
),
child: config.child child: config.child
)); ));
...@@ -190,22 +198,22 @@ class ScaffoldState extends State<Scaffold> { ...@@ -190,22 +198,22 @@ class ScaffoldState extends State<Scaffold> {
// SNACKBAR API // SNACKBAR API
Queue<ScaffoldFeatureController<SnackBar>> _snackBars = new Queue<ScaffoldFeatureController<SnackBar>>(); Queue<ScaffoldFeatureController<SnackBar>> _snackBars = new Queue<ScaffoldFeatureController<SnackBar>>();
Performance _snackBarPerformance; AnimationController _snackBarController;
Timer _snackBarTimer; Timer _snackBarTimer;
ScaffoldFeatureController showSnackBar(SnackBar snackbar) { ScaffoldFeatureController showSnackBar(SnackBar snackbar) {
_snackBarPerformance ??= SnackBar.createPerformanceController() _snackBarController ??= SnackBar.createAnimationController()
..addStatusListener(_handleSnackBarStatusChange); ..addStatusListener(_handleSnackBarStatusChange);
if (_snackBars.isEmpty) { if (_snackBars.isEmpty) {
assert(_snackBarPerformance.isDismissed); assert(_snackBarController.isDismissed);
_snackBarPerformance.forward(); _snackBarController.forward();
} }
ScaffoldFeatureController<SnackBar> controller; ScaffoldFeatureController<SnackBar> controller;
controller = new ScaffoldFeatureController<SnackBar>._( controller = new ScaffoldFeatureController<SnackBar>._(
// We provide a fallback key so that if back-to-back snackbars happen to // We provide a fallback key so that if back-to-back snackbars happen to
// match in structure, material ink splashes and highlights don't survive // match in structure, material ink splashes and highlights don't survive
// from one to the next. // from one to the next.
snackbar.withPerformance(_snackBarPerformance, fallbackKey: new UniqueKey()), snackbar.withAnimation(_snackBarController, fallbackKey: new UniqueKey()),
new Completer(), new Completer(),
() { () {
assert(_snackBars.first == controller); assert(_snackBars.first == controller);
...@@ -227,7 +235,7 @@ class ScaffoldState extends State<Scaffold> { ...@@ -227,7 +235,7 @@ class ScaffoldState extends State<Scaffold> {
_snackBars.removeFirst(); _snackBars.removeFirst();
}); });
if (_snackBars.isNotEmpty) if (_snackBars.isNotEmpty)
_snackBarPerformance.forward(); _snackBarController.forward();
break; break;
case PerformanceStatus.completed: case PerformanceStatus.completed:
setState(() { setState(() {
...@@ -242,10 +250,10 @@ class ScaffoldState extends State<Scaffold> { ...@@ -242,10 +250,10 @@ class ScaffoldState extends State<Scaffold> {
} }
void _hideSnackBar() { void _hideSnackBar() {
assert(_snackBarPerformance.status == PerformanceStatus.forward || assert(_snackBarController.status == PerformanceStatus.forward ||
_snackBarPerformance.status == PerformanceStatus.completed); _snackBarController.status == PerformanceStatus.completed);
_snackBars.first._completer.complete(); _snackBars.first._completer.complete();
_snackBarPerformance.reverse(); _snackBarController.reverse();
_snackBarTimer = null; _snackBarTimer = null;
} }
...@@ -262,7 +270,7 @@ class ScaffoldState extends State<Scaffold> { ...@@ -262,7 +270,7 @@ class ScaffoldState extends State<Scaffold> {
} }
Completer completer = new Completer(); Completer completer = new Completer();
GlobalKey<_PersistentBottomSheetState> bottomSheetKey = new GlobalKey<_PersistentBottomSheetState>(); GlobalKey<_PersistentBottomSheetState> bottomSheetKey = new GlobalKey<_PersistentBottomSheetState>();
Performance performance = BottomSheet.createPerformanceController() AnimationController controller = BottomSheet.createAnimationController()
..forward(); ..forward();
_PersistentBottomSheet bottomSheet; _PersistentBottomSheet bottomSheet;
LocalHistoryEntry entry = new LocalHistoryEntry( LocalHistoryEntry entry = new LocalHistoryEntry(
...@@ -278,7 +286,7 @@ class ScaffoldState extends State<Scaffold> { ...@@ -278,7 +286,7 @@ class ScaffoldState extends State<Scaffold> {
); );
bottomSheet = new _PersistentBottomSheet( bottomSheet = new _PersistentBottomSheet(
key: bottomSheetKey, key: bottomSheetKey,
performance: performance, animationController: controller,
onClosing: () { onClosing: () {
assert(_currentBottomSheet._widget == bottomSheet); assert(_currentBottomSheet._widget == bottomSheet);
entry.remove(); entry.remove();
...@@ -307,8 +315,8 @@ class ScaffoldState extends State<Scaffold> { ...@@ -307,8 +315,8 @@ class ScaffoldState extends State<Scaffold> {
// INTERNALS // INTERNALS
void dispose() { void dispose() {
_snackBarPerformance?.stop(); _snackBarController?.stop();
_snackBarPerformance = null; _snackBarController = null;
_snackBarTimer?.cancel(); _snackBarTimer?.cancel();
_snackBarTimer = null; _snackBarTimer = null;
super.dispose(); super.dispose();
...@@ -357,7 +365,7 @@ class ScaffoldState extends State<Scaffold> { ...@@ -357,7 +365,7 @@ class ScaffoldState extends State<Scaffold> {
if (_snackBars.length > 0) { if (_snackBars.length > 0) {
ModalRoute route = ModalRoute.of(context); ModalRoute route = ModalRoute.of(context);
if (route == null || route.isCurrent) { if (route == null || route.isCurrent) {
if (_snackBarPerformance.isCompleted && _snackBarTimer == null) if (_snackBarController.isCompleted && _snackBarTimer == null)
_snackBarTimer = new Timer(_snackBars.first._widget.duration, _hideSnackBar); _snackBarTimer = new Timer(_snackBars.first._widget.duration, _hideSnackBar);
} else { } else {
_snackBarTimer?.cancel(); _snackBarTimer?.cancel();
...@@ -420,13 +428,13 @@ class ScaffoldFeatureController<T extends Widget> { ...@@ -420,13 +428,13 @@ class ScaffoldFeatureController<T extends Widget> {
class _PersistentBottomSheet extends StatefulComponent { class _PersistentBottomSheet extends StatefulComponent {
_PersistentBottomSheet({ _PersistentBottomSheet({
Key key, Key key,
this.performance, this.animationController,
this.onClosing, this.onClosing,
this.onDismissed, this.onDismissed,
this.builder this.builder
}) : super(key: key); }) : super(key: key);
final Performance performance; final AnimationController animationController;
final VoidCallback onClosing; final VoidCallback onClosing;
final VoidCallback onDismissed; final VoidCallback onDismissed;
final WidgetBuilder builder; final WidgetBuilder builder;
...@@ -441,22 +449,22 @@ class _PersistentBottomSheetState extends State<_PersistentBottomSheet> { ...@@ -441,22 +449,22 @@ class _PersistentBottomSheetState extends State<_PersistentBottomSheet> {
void initState() { void initState() {
super.initState(); super.initState();
assert(config.performance.status == PerformanceStatus.forward); assert(config.animationController.status == PerformanceStatus.forward);
config.performance.addStatusListener(_handleStatusChange); config.animationController.addStatusListener(_handleStatusChange);
} }
void didUpdateConfig(_PersistentBottomSheet oldConfig) { void didUpdateConfig(_PersistentBottomSheet oldConfig) {
super.didUpdateConfig(oldConfig); super.didUpdateConfig(oldConfig);
assert(config.performance == oldConfig.performance); assert(config.animationController == oldConfig.animationController);
} }
void dispose() { void dispose() {
config.performance.stop(); config.animationController.stop();
super.dispose(); super.dispose();
} }
void close() { void close() {
config.performance.reverse(); config.animationController.reverse();
} }
void _handleStatusChange(PerformanceStatus status) { void _handleStatusChange(PerformanceStatus status) {
...@@ -465,15 +473,20 @@ class _PersistentBottomSheetState extends State<_PersistentBottomSheet> { ...@@ -465,15 +473,20 @@ class _PersistentBottomSheetState extends State<_PersistentBottomSheet> {
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new AlignTransition( Widget child = new BottomSheet(
performance: config.performance, animationController: config.animationController,
alignment: new AnimatedValue<FractionalOffset>(const FractionalOffset(0.0, 0.0)),
heightFactor: new AnimatedValue<double>(0.0, end: 1.0),
child: new BottomSheet(
performance: config.performance,
onClosing: config.onClosing, onClosing: config.onClosing,
builder: config.builder builder: config.builder
) );
return new AnimatedBuilder(
animation: config.animationController,
builder: (BuildContext context) {
return new Align(
alignment: const FractionalOffset(0.0, 0.0),
heightFactor: config.animationController.value,
child: child
);
}
); );
} }
......
...@@ -28,6 +28,7 @@ const Color _kSnackBackground = const Color(0xFF323232); ...@@ -28,6 +28,7 @@ const Color _kSnackBackground = const Color(0xFF323232);
const Duration _kSnackBarTransitionDuration = const Duration(milliseconds: 250); const Duration _kSnackBarTransitionDuration = const Duration(milliseconds: 250);
const Duration kSnackBarShortDisplayDuration = const Duration(milliseconds: 1500); const Duration kSnackBarShortDisplayDuration = const Duration(milliseconds: 1500);
const Duration kSnackBarMediumDisplayDuration = const Duration(milliseconds: 2750); const Duration kSnackBarMediumDisplayDuration = const Duration(milliseconds: 2750);
const Curve _snackBarHeightCurve = Curves.fastOutSlowIn;
const Curve _snackBarFadeCurve = const Interval(0.72, 1.0, curve: Curves.fastOutSlowIn); const Curve _snackBarFadeCurve = const Interval(0.72, 1.0, curve: Curves.fastOutSlowIn);
class SnackBarAction extends StatelessComponent { class SnackBarAction extends StatelessComponent {
...@@ -56,7 +57,7 @@ class SnackBar extends StatelessComponent { ...@@ -56,7 +57,7 @@ class SnackBar extends StatelessComponent {
this.content, this.content,
this.actions, this.actions,
this.duration: kSnackBarShortDisplayDuration, this.duration: kSnackBarShortDisplayDuration,
this.performance this.animation
}) : super(key: key) { }) : super(key: key) {
assert(content != null); assert(content != null);
} }
...@@ -64,10 +65,10 @@ class SnackBar extends StatelessComponent { ...@@ -64,10 +65,10 @@ class SnackBar extends StatelessComponent {
final Widget content; final Widget content;
final List<SnackBarAction> actions; final List<SnackBarAction> actions;
final Duration duration; final Duration duration;
final PerformanceView performance; final Animated<double> animation;
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(performance != null); assert(animation != null);
List<Widget> children = <Widget>[ List<Widget> children = <Widget>[
new Flexible( new Flexible(
child: new Container( child: new Container(
...@@ -81,13 +82,10 @@ class SnackBar extends StatelessComponent { ...@@ -81,13 +82,10 @@ class SnackBar extends StatelessComponent {
]; ];
if (actions != null) if (actions != null)
children.addAll(actions); children.addAll(actions);
CurvedAnimation heightAnimation = new CurvedAnimation(parent: animation, curve: _snackBarHeightCurve);
CurvedAnimation fadeAnimation = new CurvedAnimation(parent: animation, curve: _snackBarFadeCurve);
ThemeData theme = Theme.of(context); ThemeData theme = Theme.of(context);
return new ClipRect( Widget child = new Material(
child: new AlignTransition(
performance: performance,
alignment: new AnimatedValue<FractionalOffset>(const FractionalOffset(0.0, 0.0)),
heightFactor: new AnimatedValue<double>(0.0, end: 1.0, curve: Curves.fastOutSlowIn),
child: new Material(
elevation: 6, elevation: 6,
color: _kSnackBackground, color: _kSnackBackground,
child: new Container( child: new Container(
...@@ -100,8 +98,7 @@ class SnackBar extends StatelessComponent { ...@@ -100,8 +98,7 @@ class SnackBar extends StatelessComponent {
text: Typography.white text: Typography.white
), ),
child: new FadeTransition( child: new FadeTransition(
performance: performance, opacity: fadeAnimation,
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: _snackBarFadeCurve),
child: new Row( child: new Row(
children: children, children: children,
alignItems: FlexAlignItems.center alignItems: FlexAlignItems.center
...@@ -109,27 +106,37 @@ class SnackBar extends StatelessComponent { ...@@ -109,27 +106,37 @@ class SnackBar extends StatelessComponent {
) )
) )
) )
) );
return new ClipRect(
child: new AnimatedBuilder(
animation: heightAnimation,
builder: (BuildContext context) {
return new Align(
alignment: const FractionalOffset(0.0, 0.0),
heightFactor: heightAnimation.value,
child: child
);
}
) )
); );
} }
// API for Scaffold.addSnackBar(): // API for Scaffold.addSnackBar():
static Performance createPerformanceController() { static AnimationController createAnimationController() {
return new Performance( return new AnimationController(
duration: _kSnackBarTransitionDuration, duration: _kSnackBarTransitionDuration,
debugLabel: 'SnackBar' debugLabel: 'SnackBar'
); );
} }
SnackBar withPerformance(Performance newPerformance, { Key fallbackKey }) { SnackBar withAnimation(Animated<double> newAnimation, { Key fallbackKey }) {
return new SnackBar( return new SnackBar(
key: key ?? fallbackKey, key: key ?? fallbackKey,
content: content, content: content,
actions: actions, actions: actions,
duration: duration, duration: duration,
performance: newPerformance animation: newAnimation
); );
} }
} }
...@@ -415,10 +415,10 @@ class TabBarSelection<T> extends StatefulComponent { ...@@ -415,10 +415,10 @@ class TabBarSelection<T> extends StatefulComponent {
class TabBarSelectionState<T> extends State<TabBarSelection<T>> { class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
Animation get animation => _controller.view; Animated<double> get animation => _controller.view;
// Both the TabBar and TabBarView classes access _performance because they // Both the TabBar and TabBarView classes access _performance because they
// alternately drive selection progress between tabs. // alternately drive selection progress between tabs.
final AnimationController _controller = new AnimationController(duration: _kTabBarScroll, progress: 1.0); final AnimationController _controller = new AnimationController(duration: _kTabBarScroll, value: 1.0);
final Map<T, int> _valueToIndex = new Map<T, int>(); final Map<T, int> _valueToIndex = new Map<T, int>();
void _initValueToIndex() { void _initValueToIndex() {
...@@ -480,22 +480,22 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> { ...@@ -480,22 +480,22 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
// one. Convert progress to reflect the fact that we're now moving between (just) // one. Convert progress to reflect the fact that we're now moving between (just)
// the previous and current selection index. // the previous and current selection index.
double progress; double value;
if (_controller.status == PerformanceStatus.completed) if (_controller.status == PerformanceStatus.completed)
progress = 0.0; value = 0.0;
else if (_previousValue == values.first) else if (_previousValue == values.first)
progress = _controller.progress; value = _controller.value;
else if (_previousValue == values.last) else if (_previousValue == values.last)
progress = 1.0 - _controller.progress; value = 1.0 - _controller.value;
else if (previousIndex < index) else if (previousIndex < index)
progress = (_controller.progress - 0.5) * 2.0; value = (_controller.value - 0.5) * 2.0;
else else
progress = 1.0 - _controller.progress * 2.0; value = 1.0 - _controller.value * 2.0;
_controller _controller
..progress = progress ..value = value
..forward().then((_) { ..forward().then((_) {
if (_controller.progress == 1.0) { if (_controller.value == 1.0) {
if (config.onChanged != null) if (config.onChanged != null)
config.onChanged(_value); config.onChanged(_value);
_valueIsChanging = false; _valueIsChanging = false;
...@@ -612,7 +612,7 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -612,7 +612,7 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
_valueIsChanging = true; _valueIsChanging = true;
} }
Rect oldRect = _indicatorRect; Rect oldRect = _indicatorRect;
double t = _selection.animation.progress; double t = _selection.animation.value;
if (_valueIsChanging) { if (_valueIsChanging) {
// When _valueIsChanging is true, we're animating based on a ticker and // When _valueIsChanging is true, we're animating based on a ticker and
// want to curve the animation. When _valueIsChanging is false, we're // want to curve the animation. When _valueIsChanging is false, we're
...@@ -676,9 +676,9 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -676,9 +676,9 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
labelColor = isSelectedTab ? selectedColor : color; labelColor = isSelectedTab ? selectedColor : color;
if (_selection.valueIsChanging) { if (_selection.valueIsChanging) {
if (isSelectedTab) if (isSelectedTab)
labelColor = Color.lerp(color, selectedColor, _selection.animation.progress); labelColor = Color.lerp(color, selectedColor, _selection.animation.value);
else if (isPreviouslySelectedTab) else if (isPreviouslySelectedTab)
labelColor = Color.lerp(selectedColor, color, _selection.animation.progress); labelColor = Color.lerp(selectedColor, color, _selection.animation.value);
} }
} }
return new _Tab( return new _Tab(
...@@ -876,7 +876,7 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe ...@@ -876,7 +876,7 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
return; return;
// The TabBar is driving the TabBarSelection performance. // The TabBar is driving the TabBarSelection performance.
final Animation animation = _selection.animation; final Animated<double> animation = _selection.animation;
if (animation.status == PerformanceStatus.completed) { if (animation.status == PerformanceStatus.completed) {
_updateItemsAndScrollBehavior(); _updateItemsAndScrollBehavior();
...@@ -898,9 +898,9 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe ...@@ -898,9 +898,9 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
} }
if (_scrollDirection == AnimationDirection.forward) if (_scrollDirection == AnimationDirection.forward)
scrollTo(animation.progress); scrollTo(animation.value);
else else
scrollTo(1.0 - animation.progress); scrollTo(1.0 - animation.value);
} }
void dispatchOnScroll() { void dispatchOnScroll() {
...@@ -911,9 +911,9 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe ...@@ -911,9 +911,9 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
final AnimationController controller = _selection._controller; final AnimationController controller = _selection._controller;
if (_selection.index == 0 || _selection.index == _tabCount - 1) if (_selection.index == 0 || _selection.index == _tabCount - 1)
controller.progress = scrollOffset; controller.value = scrollOffset;
else else
controller.progress = scrollOffset / 2.0; controller.value = scrollOffset / 2.0;
} }
Future fling(Offset scrollVelocity) { Future fling(Offset scrollVelocity) {
......
...@@ -266,7 +266,7 @@ class _TooltipOverlay extends StatelessComponent { ...@@ -266,7 +266,7 @@ class _TooltipOverlay extends StatelessComponent {
screenEdgeMargin: screenEdgeMargin, screenEdgeMargin: screenEdgeMargin,
preferBelow: preferBelow preferBelow: preferBelow
), ),
child: new FadeTransition( child: new OldFadeTransition(
performance: performance, performance: performance,
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: Curves.ease), opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: Curves.ease),
child: new Opacity( child: new Opacity(
......
...@@ -91,9 +91,9 @@ class _Entry { ...@@ -91,9 +91,9 @@ class _Entry {
} }
} }
typedef Widget TransitionBuilderCallback(Animation animation, Widget child); typedef Widget TransitionBuilderCallback(Animated<double> animation, Widget child);
Widget _identityTransition(Animation animation, Widget child) => child; Widget _identityTransition(Animated<double> animation, Widget child) => child;
class EnterExitTransition extends StatefulComponent { class EnterExitTransition extends StatefulComponent {
EnterExitTransition({ EnterExitTransition({
......
...@@ -63,47 +63,47 @@ class _TransitionState extends State<TransitionComponent> { ...@@ -63,47 +63,47 @@ class _TransitionState extends State<TransitionComponent> {
} }
} }
abstract class AnimationWatchingComponent extends StatefulComponent { abstract class AnimatedComponent extends StatefulComponent {
AnimationWatchingComponent({ AnimatedComponent({
Key key, Key key,
this.watchable this.animation
}) : super(key: key) { }) : super(key: key) {
assert(watchable != null); assert(animation != null);
} }
final Watchable watchable; final Animated<Object> animation;
Widget build(BuildContext context); Widget build(BuildContext context);
_AnimationWatchingComponentState createState() => new _AnimationWatchingComponentState(); _AnimatedComponentState createState() => new _AnimatedComponentState();
void debugFillDescription(List<String> description) { void debugFillDescription(List<String> description) {
super.debugFillDescription(description); super.debugFillDescription(description);
description.add('watchable: $watchable'); description.add('animation: $animation');
} }
} }
class _AnimationWatchingComponentState extends State<AnimationWatchingComponent> { class _AnimatedComponentState extends State<AnimatedComponent> {
void initState() { void initState() {
super.initState(); super.initState();
config.watchable.addListener(_handleTick); config.animation.addListener(_handleTick);
} }
void didUpdateConfig(AnimationWatchingComponent oldConfig) { void didUpdateConfig(AnimatedComponent oldConfig) {
if (config.watchable != oldConfig.watchable) { if (config.animation != oldConfig.animation) {
oldConfig.watchable.removeListener(_handleTick); oldConfig.animation.removeListener(_handleTick);
config.watchable.addListener(_handleTick); config.animation.addListener(_handleTick);
} }
} }
void dispose() { void dispose() {
config.watchable.removeListener(_handleTick); config.animation.removeListener(_handleTick);
super.dispose(); super.dispose();
} }
void _handleTick() { void _handleTick() {
setState(() { setState(() {
// The watchable's state is our build state, and it changed already. // The animation's state is our build state, and it changed already.
}); });
} }
...@@ -146,24 +146,22 @@ class SlideTransition extends TransitionWithChild { ...@@ -146,24 +146,22 @@ class SlideTransition extends TransitionWithChild {
} }
} }
class ScaleTransition extends TransitionWithChild { class ScaleTransition extends AnimatedComponent {
ScaleTransition({ ScaleTransition({
Key key, Key key,
this.scale, Animated<double> scale,
this.alignment: const FractionalOffset(0.5, 0.5), this.alignment: const FractionalOffset(0.5, 0.5),
PerformanceView performance, this.child
Widget child }) : scale = scale, super(key: key, animation: scale);
}) : super(key: key,
performance: performance,
child: child);
final AnimatedValue<double> scale; final Animated<double> scale;
final FractionalOffset alignment; final FractionalOffset alignment;
final Widget child;
Widget buildWithChild(BuildContext context, Widget child) { Widget build(BuildContext context) {
performance.updateVariable(scale); double scaleValue = scale.value;
Matrix4 transform = new Matrix4.identity() Matrix4 transform = new Matrix4.identity()
..scale(scale.value, scale.value); ..scale(scaleValue, scaleValue);
return new Transform( return new Transform(
transform: transform, transform: transform,
alignment: alignment, alignment: alignment,
...@@ -195,8 +193,8 @@ class RotationTransition extends TransitionWithChild { ...@@ -195,8 +193,8 @@ class RotationTransition extends TransitionWithChild {
} }
} }
class FadeTransition extends TransitionWithChild { class OldFadeTransition extends TransitionWithChild {
FadeTransition({ OldFadeTransition({
Key key, Key key,
this.opacity, this.opacity,
PerformanceView performance, PerformanceView performance,
...@@ -213,6 +211,21 @@ class FadeTransition extends TransitionWithChild { ...@@ -213,6 +211,21 @@ class FadeTransition extends TransitionWithChild {
} }
} }
class FadeTransition extends AnimatedComponent {
FadeTransition({
Key key,
Animated<double> opacity,
this.child
}) : opacity = opacity, super(key: key, animation: opacity);
final Animated<double> opacity;
final Widget child;
Widget build(BuildContext context) {
return new Opacity(opacity: opacity.value, child: child);
}
}
class ColorTransition extends TransitionWithChild { class ColorTransition extends TransitionWithChild {
ColorTransition({ ColorTransition({
Key key, Key key,
...@@ -352,12 +365,12 @@ class BuilderTransition extends TransitionComponent { ...@@ -352,12 +365,12 @@ class BuilderTransition extends TransitionComponent {
} }
} }
class AnimationWatchingBuilder extends AnimationWatchingComponent { class AnimatedBuilder extends AnimatedComponent {
AnimationWatchingBuilder({ AnimatedBuilder({
Key key, Key key,
Watchable watchable, Animated<Object> animation,
this.builder this.builder
}) : super(key: key, watchable: watchable); }) : super(key: key, animation: animation);
final WidgetBuilder builder; final WidgetBuilder builder;
......
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