Commit aabd1ce4 authored by Adam Barth's avatar Adam Barth

Merge pull request #1317 from abarth/port_widgets

Port most of widgets to AnimationController
parents e4940a01 24872f69
......@@ -41,10 +41,9 @@ class Theme extends InheritedWidget {
}
}
/// An animated value that interpolates [BoxConstraint]s.
class AnimatedThemeDataValue extends AnimatedValue<ThemeData> {
AnimatedThemeDataValue(ThemeData begin, { ThemeData end, Curve curve, Curve reverseCurve })
: super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
/// An animated value that interpolates [ThemeData]s.
class ThemeDataTween extends Tween<ThemeData> {
ThemeDataTween({ ThemeData begin, ThemeData end }) : super(begin: begin, end: end);
ThemeData lerp(double t) => ThemeData.lerp(begin, end, t);
}
......@@ -71,18 +70,18 @@ class AnimatedTheme extends AnimatedWidgetBase {
}
class _AnimatedThemeState extends AnimatedWidgetBaseState<AnimatedTheme> {
AnimatedThemeDataValue _data;
ThemeDataTween _data;
void forEachVariable(VariableVisitor visitor) {
void forEachTween(TweenVisitor visitor) {
// TODO(ianh): Use constructor tear-offs when it becomes possible
_data = visitor(_data, config.data, (dynamic value) => new AnimatedThemeDataValue(value));
_data = visitor(_data, config.data, (dynamic value) => new ThemeDataTween(begin: value));
assert(_data != null);
}
Widget build(BuildContext context) {
return new Theme(
child: config.child,
data: _data.value
data: _data.evaluate(animation)
);
}
......
......@@ -72,23 +72,23 @@ class Dismissable extends StatefulComponent {
class _DismissableState extends State<Dismissable> {
void initState() {
super.initState();
_dismissPerformance = new Performance(duration: _kCardDismissDuration);
_dismissPerformance.addStatusListener((PerformanceStatus status) {
_dismissController = new AnimationController(duration: _kCardDismissDuration);
_dismissController.addStatusListener((PerformanceStatus status) {
if (status == PerformanceStatus.completed)
_handleDismissCompleted();
});
}
Performance _dismissPerformance;
Performance _resizePerformance;
AnimationController _dismissController;
AnimationController _resizeController;
Size _size;
double _dragExtent = 0.0;
bool _dragUnderway = false;
void dispose() {
_dismissPerformance?.stop();
_resizePerformance?.stop();
_dismissController?.stop();
_resizeController?.stop();
super.dispose();
}
......@@ -101,11 +101,11 @@ class _DismissableState extends State<Dismissable> {
void _handleDismissCompleted() {
if (!_dragUnderway)
_startResizePerformance();
_startResizeAnimation();
}
bool get _isActive {
return _size != null && (_dragUnderway || _dismissPerformance.isAnimating);
return _size != null && (_dragUnderway || _dismissController.isAnimating);
}
void _maybeCallOnResized() {
......@@ -118,21 +118,20 @@ class _DismissableState extends State<Dismissable> {
config.onDismissed();
}
void _startResizePerformance() {
void _startResizeAnimation() {
assert(_size != null);
assert(_dismissPerformance != null);
assert(_dismissPerformance.isCompleted);
assert(_resizePerformance == null);
assert(_dismissController != null);
assert(_dismissController.isCompleted);
assert(_resizeController == null);
setState(() {
_resizePerformance = new Performance()
..duration = _kCardResizeDuration
_resizeController = new AnimationController(duration: _kCardResizeDuration)
..addListener(_handleResizeProgressChanged);
_resizePerformance.play();
_resizeController.forward();
});
}
void _handleResizeProgressChanged() {
if (_resizePerformance.isCompleted)
if (_resizeController.isCompleted)
_maybeCallOnDismissed();
else
_maybeCallOnResized();
......@@ -141,18 +140,18 @@ class _DismissableState extends State<Dismissable> {
void _handleDragStart(_) {
setState(() {
_dragUnderway = true;
if (_dismissPerformance.isAnimating) {
_dragExtent = _dismissPerformance.progress * _size.width * _dragExtent.sign;
_dismissPerformance.stop();
if (_dismissController.isAnimating) {
_dragExtent = _dismissController.value * _size.width * _dragExtent.sign;
_dismissController.stop();
} else {
_dragExtent = 0.0;
_dismissPerformance.progress = 0.0;
_dismissController.value = 0.0;
}
});
}
void _handleDragUpdate(double delta) {
if (!_isActive || _dismissPerformance.isAnimating)
if (!_isActive || _dismissController.isAnimating)
return;
double oldDragExtent = _dragExtent;
......@@ -180,11 +179,11 @@ class _DismissableState extends State<Dismissable> {
// Rebuild to update the new drag endpoint.
// The sign of _dragExtent is part of our build state;
// the actual value is not, it's just used to configure
// the performances.
// the animations.
});
}
if (!_dismissPerformance.isAnimating)
_dismissPerformance.progress = _dragExtent.abs() / _size.width;
if (!_dismissController.isAnimating)
_dismissController.value = _dragExtent.abs() / _size.width;
}
bool _isFlingGesture(ui.Offset velocity) {
......@@ -217,20 +216,20 @@ class _DismissableState extends State<Dismissable> {
}
void _handleDragEnd(ui.Offset velocity) {
if (!_isActive || _dismissPerformance.isAnimating)
if (!_isActive || _dismissController.isAnimating)
return;
setState(() {
_dragUnderway = false;
if (_dismissPerformance.isCompleted) {
_startResizePerformance();
if (_dismissController.isCompleted) {
_startResizeAnimation();
} else if (_isFlingGesture(velocity)) {
double flingVelocity = _directionIsYAxis ? velocity.dy : velocity.dx;
_dragExtent = flingVelocity.sign;
_dismissPerformance.fling(velocity: flingVelocity.abs() * _kFlingVelocityScale);
} else if (_dismissPerformance.progress > _kDismissCardThreshold) {
_dismissPerformance.forward();
_dismissController.fling(velocity: flingVelocity.abs() * _kFlingVelocityScale);
} else if (_dismissController.value > _kDismissCardThreshold) {
_dismissController.forward();
} else {
_dismissPerformance.reverse();
_dismissController.reverse();
}
});
}
......@@ -250,20 +249,26 @@ class _DismissableState extends State<Dismissable> {
}
Widget build(BuildContext context) {
if (_resizePerformance != null) {
if (_resizeController != null) {
// make sure you remove this widget once it's been dismissed!
assert(_resizePerformance.status == PerformanceStatus.forward);
assert(_resizeController.status == PerformanceStatus.forward);
AnimatedValue<double> squashAxisExtent = new AnimatedValue<double>(
_directionIsYAxis ? _size.width : _size.height,
end: 0.0,
Animated<double> squashAxisExtent = new Tween<double>(
begin: _directionIsYAxis ? _size.width : _size.height,
end: 0.0
).animate(new CurvedAnimation(
parent: _resizeController,
curve: _kCardResizeTimeCurve
);
return new SquashTransition(
performance: _resizePerformance.view,
width: _directionIsYAxis ? squashAxisExtent : null,
height: !_directionIsYAxis ? squashAxisExtent : null
));
return new AnimatedBuilder(
animation: squashAxisExtent,
builder: (BuildContext context, Widget child) {
return new SizedBox(
width: _directionIsYAxis ? squashAxisExtent.value : null,
height: !_directionIsYAxis ? squashAxisExtent.value : null
);
}
);
}
......@@ -278,11 +283,10 @@ class _DismissableState extends State<Dismissable> {
child: new SizeObserver(
onSizeChanged: _handleSizeChanged,
child: new SlideTransition(
performance: _dismissPerformance.view,
position: new AnimatedValue<FractionalOffset>(
FractionalOffset.zero,
position: new Tween<FractionalOffset>(
begin: FractionalOffset.zero,
end: _activeCardDragEndPoint
),
).animate(_dismissController),
child: config.child
)
)
......
......@@ -378,7 +378,7 @@ class HeroParty {
Animated<double> _currentAnimation;
void _clearCurrentPerformance() {
void _clearCurrentAnimation() {
_currentAnimation?.removeStatusListener(_handleUpdate);
_currentAnimation = null;
}
......@@ -386,7 +386,7 @@ class HeroParty {
void setAnimation(Animated<double> animation) {
assert(animation != null || _heroes.length == 0);
if (animation != _currentAnimation) {
_clearCurrentPerformance();
_clearCurrentAnimation();
_currentAnimation = animation;
_currentAnimation?.addStatusListener(_handleUpdate);
}
......@@ -402,7 +402,7 @@ class HeroParty {
source._resetChild();
}
_heroes.clear();
_clearCurrentPerformance();
_clearCurrentAnimation();
if (onQuestFinished != null)
onQuestFinished();
}
......
......@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/animation.dart';
import 'package:flutter/rendering.dart';
......@@ -42,7 +41,7 @@ class MimicOverlayEntry {
// Animation state
GlobalKey _targetKey;
Curve _curve;
Performance _performance;
AnimationController _controller;
/// Animate the entry to the location of the widget that has the given target key.
///
......@@ -63,10 +62,10 @@ class MimicOverlayEntry {
_targetKey = targetKey;
_curve = curve;
// TODO(abarth): Support changing the animation target when in flight.
assert(_performance == null);
_performance = new Performance(duration: duration)
assert(_controller == null);
_controller = new AnimationController(duration: duration)
..addListener(_overlayEntry.markNeedsBuild);
return _performance.play();
return _controller.forward();
}
/// Cause the overlay entry to rebuild during the next pipeline flush.
......@@ -84,8 +83,8 @@ class MimicOverlayEntry {
void dispose() {
_targetKey = null;
_curve = null;
_performance?.stop();
_performance = null;
_controller?.stop();
_controller = null;
_key.stopMimic();
_key = null;
_overlayEntry.remove();
......@@ -98,16 +97,14 @@ class MimicOverlayEntry {
Rect globalBounds = _initialGlobalBounds;
Point globalPosition = globalBounds.topLeft;
if (_targetKey != null) {
assert(_performance != null);
assert(_controller != null);
assert(_curve != null);
RenderBox box = _targetKey.currentContext?.findRenderObject();
if (box != null) {
// TODO(abarth): Handle the case where the transform here isn't just a translation.
Point localPosition = box.localToGlobal(Point.origin);
double t = _curve.transform(_performance.progress);
// TODO(abarth): Add Point.lerp.
globalPosition = new Point(ui.lerpDouble(globalPosition.x, localPosition.x, t),
ui.lerpDouble(globalPosition.y, localPosition.y, t));
double t = _curve.transform(_controller.value);
globalPosition = Point.lerp(globalPosition, localPosition, t);
}
}
......
......@@ -96,7 +96,7 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
Animated<double> _animation;
AnimationController _controller;
/// Called to create the Performance object that will drive the transitions to
/// Called to create the animation controller that will drive the transitions to
/// this route from the previous one, and back to the previous route from this
/// one.
AnimationController createAnimationController() {
......@@ -105,8 +105,8 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
return new AnimationController(duration: duration, debugLabel: debugLabel);
}
/// Called to create the PerformanceView that exposes the current progress of
/// the transition controlled by the Performance object created by
/// Called to create the animation that exposes the current progress of
/// the transition controlled by the animation controller created by
/// [createAnimationController()].
Animated<double> createAnimation() {
assert(_controller != null);
......@@ -166,32 +166,32 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
}
void didPopNext(Route nextRoute) {
_updateForwardPerformance(nextRoute);
_updateForwardAnimation(nextRoute);
super.didPopNext(nextRoute);
}
void didChangeNext(Route nextRoute) {
_updateForwardPerformance(nextRoute);
_updateForwardAnimation(nextRoute);
super.didChangeNext(nextRoute);
}
void _updateForwardPerformance(Route nextRoute) {
void _updateForwardAnimation(Route nextRoute) {
if (nextRoute is TransitionRoute && canTransitionTo(nextRoute) && nextRoute.canTransitionFrom(this)) {
Animated<double> current = _forwardAnimation.masterAnimation;
if (current != null) {
if (current is TrainHoppingAnimation) {
TrainHoppingAnimation newPerformance;
newPerformance = new TrainHoppingAnimation(
TrainHoppingAnimation newAnimation;
newAnimation = new TrainHoppingAnimation(
current.currentTrain,
nextRoute.animation,
onSwitchedTrain: () {
assert(_forwardAnimation.masterAnimation == newPerformance);
assert(newPerformance.currentTrain == nextRoute.animation);
_forwardAnimation.masterAnimation = newPerformance.currentTrain;
newPerformance.dispose();
assert(_forwardAnimation.masterAnimation == newAnimation);
assert(newAnimation.currentTrain == nextRoute.animation);
_forwardAnimation.masterAnimation = newAnimation.currentTrain;
newAnimation.dispose();
}
);
_forwardAnimation.masterAnimation = newPerformance;
_forwardAnimation.masterAnimation = newAnimation;
current.dispose();
} else {
_forwardAnimation.masterAnimation = new TrainHoppingAnimation(current, nextRoute.animation);
......@@ -322,7 +322,7 @@ class _ModalScopeState extends State<_ModalScope> {
void _animationStatusChanged(PerformanceStatus status) {
setState(() {
// The performances' states are our build state, and they changed already.
// The animation's states are our build state, and they changed already.
});
}
......
......@@ -24,24 +24,24 @@ abstract class StatusTransitionComponent extends StatefulComponent {
class _StatusTransitionState extends State<StatusTransitionComponent> {
void initState() {
super.initState();
config.animation.addStatusListener(_performanceStatusChanged);
config.animation.addStatusListener(_animationStatusChanged);
}
void didUpdateConfig(StatusTransitionComponent oldConfig) {
if (config.animation != oldConfig.animation) {
oldConfig.animation.removeStatusListener(_performanceStatusChanged);
config.animation.addStatusListener(_performanceStatusChanged);
oldConfig.animation.removeStatusListener(_animationStatusChanged);
config.animation.addStatusListener(_animationStatusChanged);
}
}
void dispose() {
config.animation.removeStatusListener(_performanceStatusChanged);
config.animation.removeStatusListener(_animationStatusChanged);
super.dispose();
}
void _performanceStatusChanged(PerformanceStatus status) {
void _animationStatusChanged(PerformanceStatus status) {
setState(() {
// The performance's state is our build state, and it changed already.
// The animation's state is our build state, and it changed already.
});
}
......
......@@ -126,23 +126,25 @@ abstract class TransitionWithChild extends TransitionComponent {
Widget buildWithChild(BuildContext context, Widget child);
}
class SlideTransition extends TransitionWithChild {
class SlideTransition extends AnimatedComponent {
SlideTransition({
Key key,
this.position,
Animated<FractionalOffset> position,
PerformanceView performance,
this.transformHitTests: true,
Widget child
}) : super(key: key,
performance: performance,
child: child);
this.child
}) : position = position, super(key: key, animation: position);
final AnimatedValue<FractionalOffset> position;
bool transformHitTests;
final Animated<FractionalOffset> position;
final bool transformHitTests;
final Widget child;
Widget buildWithChild(BuildContext context, Widget child) {
performance.updateVariable(position);
return new FractionalTranslation(translation: position.value, transformHitTests: transformHitTests, child: child);
Widget build(BuildContext context) {
return new FractionalTranslation(
translation: position.value,
transformHitTests: transformHitTests,
child: child
);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment