Merge pull request #1487 from abarth/merge_curve_into_interval
Give Interval a Curve to apply between start and end
diff --git a/examples/widgets/progress_indicator.dart b/examples/widgets/progress_indicator.dart
index e769784..b4b2b41 100644
--- a/examples/widgets/progress_indicator.dart
+++ b/examples/widgets/progress_indicator.dart
@@ -18,9 +18,8 @@
..variable = new AnimatedValue<double>(
0.0,
end: 1.0,
- curve: ease,
- reverseCurve: ease,
- interval: new Interval(0.0, 0.9)
+ curve: new Interval(0.0, 0.9, curve: ease),
+ reverseCurve: ease
);
valueAnimation.addStatusListener((PerformanceStatus status) {
if (status == PerformanceStatus.dismissed || status == PerformanceStatus.completed)
diff --git a/packages/flutter/lib/src/animation/animated_value.dart b/packages/flutter/lib/src/animation/animated_value.dart
index f42c4b8..9b4a8da 100644
--- a/packages/flutter/lib/src/animation/animated_value.dart
+++ b/packages/flutter/lib/src/animation/animated_value.dart
@@ -25,70 +25,43 @@
String toString();
}
-/// Used by [AnimationPerformance] to convert the timing of a performance to a different timescale.
+/// Used by [Performance] to convert the timing of a performance to a different timescale.
/// For example, by setting different values for the interval and reverseInterval, a performance
/// can be made to take longer in one direction that the other.
class AnimationTiming {
- AnimationTiming({
- this.interval: const Interval(0.0, 1.0),
- this.reverseInterval,
- this.curve: linear,
- this.reverseCurve
- });
+ AnimationTiming({ this.curve, this.reverseCurve });
- /// The interval during which this timing is active in the forward direction
- Interval interval;
-
- /// The interval during which this timing is active in the reverse direction
- ///
- /// If this field is null, the timing defaults to using [interval] in both directions.
- Interval reverseInterval;
-
- /// The curve that this timing applies to the animation clock in the forward direction
+ /// The curve to use in the forward direction
Curve curve;
- /// The curve that this timing applies to the animation clock in the reverse direction
+ /// The curve to use in the reverse direction
///
- /// If this field is null, the timing defaults to using [curve] in both directions.
+ /// If this field is null, use [curve] in both directions.
Curve reverseCurve;
/// Applies this timing to the given animation clock value in the given direction
double transform(double t, AnimationDirection direction) {
- Interval interval = _getInterval(direction);
- if (interval != null)
- t = interval.transform(t);
- assert(t >= 0.0 && t <= 1.0);
+ Curve activeCurve = _getActiveCurve(direction);
+ if (activeCurve == null)
+ return t;
if (t == 0.0 || t == 1.0) {
- assert(t == _applyCurve(t, direction).round().toDouble());
+ assert(activeCurve.transform(t).round() == t);
return t;
}
- return _applyCurve(t, direction);
+ return activeCurve.transform(t);
}
- Interval _getInterval(AnimationDirection direction) {
- if (direction == AnimationDirection.forward || reverseInterval == null)
- return interval;
- return reverseInterval;
- }
-
- Curve _getCurve(AnimationDirection direction) {
+ Curve _getActiveCurve(AnimationDirection direction) {
if (direction == AnimationDirection.forward || reverseCurve == null)
return curve;
return reverseCurve;
}
-
- double _applyCurve(double t, AnimationDirection direction) {
- Curve curve = _getCurve(direction);
- if (curve == null)
- return t;
- return curve.transform(t);
- }
}
/// An animated variable with a concrete type
class AnimatedValue<T extends dynamic> extends AnimationTiming implements Animatable {
- AnimatedValue(this.begin, { this.end, Interval interval, Interval reverseInterval, Curve curve, Curve reverseCurve })
- : super(interval: interval, reverseInterval: reverseInterval, curve: curve, reverseCurve: reverseCurve) {
+ AnimatedValue(this.begin, { this.end, Curve curve, Curve reverseCurve })
+ : super(curve: curve, reverseCurve: reverseCurve) {
value = begin;
}
@@ -125,8 +98,8 @@
/// This class specializes the interpolation of AnimatedValue<Color> to be
/// appropriate for colors.
class AnimatedColorValue extends AnimatedValue<Color> {
- AnimatedColorValue(Color begin, { Color end, Interval interval, Interval reverseInterval, Curve curve, Curve reverseCurve })
- : super(begin, end: end, interval: interval, reverseInterval: reverseInterval, curve: curve, reverseCurve: reverseCurve);
+ 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);
}
@@ -136,8 +109,8 @@
/// This class specializes the interpolation of AnimatedValue<Rect> to be
/// appropriate for rectangles.
class AnimatedRectValue extends AnimatedValue<Rect> {
- AnimatedRectValue(Rect begin, { Rect end, Interval interval, Interval reverseInterval, Curve curve, Curve reverseCurve })
- : super(begin, end: end, interval: interval, reverseInterval: reverseInterval, curve: curve, reverseCurve: reverseCurve);
+ 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);
}
diff --git a/packages/flutter/lib/src/animation/curves.dart b/packages/flutter/lib/src/animation/curves.dart
index 31fb4a9..5b44cc4 100644
--- a/packages/flutter/lib/src/animation/curves.dart
+++ b/packages/flutter/lib/src/animation/curves.dart
@@ -27,9 +27,9 @@
double transform(double t) => t;
}
-/// A curve that is 0.0 until start, then linear from 0.0 to 1.0 at end, then 1.0
+/// A curve that is 0.0 until start, then curved from 0.0 to 1.0 at end, then 1.0
class Interval implements Curve {
- const Interval(this.start, this.end);
+ const Interval(this.start, this.end, { this.curve: linear });
/// The smallest value for which this interval is 0.0
final double start;
@@ -37,12 +37,18 @@
/// The smallest value for which this interval is 1.0
final double end;
+ /// The curve to apply between [start] and [end]
+ final Curve curve;
+
double transform(double t) {
assert(start >= 0.0);
assert(start <= 1.0);
assert(end >= 0.0);
assert(end <= 1.0);
- return ((t - start) / (end - start)).clamp(0.0, 1.0);
+ t = ((t - start) / (end - start)).clamp(0.0, 1.0);
+ if (t == 0.0 || t == 1.0)
+ return t;
+ return curve.transform(t);
}
}
diff --git a/packages/flutter/lib/src/widgets/animated_container.dart b/packages/flutter/lib/src/widgets/animated_container.dart
index 4d1f1d4..e9c56a1 100644
--- a/packages/flutter/lib/src/widgets/animated_container.dart
+++ b/packages/flutter/lib/src/widgets/animated_container.dart
@@ -9,29 +9,29 @@
import 'package:vector_math/vector_math_64.dart';
class AnimatedBoxConstraintsValue extends AnimatedValue<BoxConstraints> {
- AnimatedBoxConstraintsValue(BoxConstraints begin, { BoxConstraints end, Curve curve: linear })
- : super(begin, end: end, curve: curve);
+ AnimatedBoxConstraintsValue(BoxConstraints begin, { BoxConstraints end, Curve curve, Curve reverseCurve })
+ : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
BoxConstraints lerp(double t) => BoxConstraints.lerp(begin, end, t);
}
class AnimatedBoxDecorationValue extends AnimatedValue<BoxDecoration> {
- AnimatedBoxDecorationValue(BoxDecoration begin, { BoxDecoration end, Curve curve: linear })
- : super(begin, end: end, curve: curve);
+ AnimatedBoxDecorationValue(BoxDecoration begin, { BoxDecoration end, Curve curve, Curve reverseCurve })
+ : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
BoxDecoration lerp(double t) => BoxDecoration.lerp(begin, end, t);
}
class AnimatedEdgeDimsValue extends AnimatedValue<EdgeDims> {
- AnimatedEdgeDimsValue(EdgeDims begin, { EdgeDims end, Curve curve: linear })
- : super(begin, end: end, curve: curve);
+ AnimatedEdgeDimsValue(EdgeDims begin, { EdgeDims end, Curve curve, Curve reverseCurve })
+ : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
EdgeDims lerp(double t) => EdgeDims.lerp(begin, end, t);
}
class AnimatedMatrix4Value extends AnimatedValue<Matrix4> {
- AnimatedMatrix4Value(Matrix4 begin, { Matrix4 end, Curve curve: linear })
- : super(begin, end: end, curve: curve);
+ AnimatedMatrix4Value(Matrix4 begin, { Matrix4 end, Curve curve, Curve reverseCurve })
+ : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
Matrix4 lerp(double t) {
// TODO(mpcomplete): Animate the full matrix. Will animating the cells
diff --git a/packages/flutter/lib/src/widgets/dismissable.dart b/packages/flutter/lib/src/widgets/dismissable.dart
index d019580..b9c11e2 100644
--- a/packages/flutter/lib/src/widgets/dismissable.dart
+++ b/packages/flutter/lib/src/widgets/dismissable.dart
@@ -12,7 +12,7 @@
const Duration _kCardDismissFadeout = const Duration(milliseconds: 200);
const Duration _kCardDismissResize = const Duration(milliseconds: 300);
-final Interval _kCardDismissResizeInterval = new Interval(0.4, 1.0);
+const Curve _kCardDismissResizeCurve = const Interval(0.4, 1.0, curve: ease);
const double _kMinFlingVelocity = 700.0;
const double _kMinFlingVelocityDelta = 400.0;
const double _kFlingVelocityScale = 1.0 / 300.0;
@@ -226,8 +226,7 @@
AnimatedValue<double> squashAxisExtent = new AnimatedValue<double>(
_directionIsYAxis ? _size.width : _size.height,
end: 0.0,
- curve: ease,
- interval: _kCardDismissResizeInterval
+ curve: _kCardDismissResizeCurve
);
return new SquashTransition(
diff --git a/packages/flutter/lib/src/widgets/popup_menu.dart b/packages/flutter/lib/src/widgets/popup_menu.dart
index 3812fb7..c6af624 100644
--- a/packages/flutter/lib/src/widgets/popup_menu.dart
+++ b/packages/flutter/lib/src/widgets/popup_menu.dart
@@ -29,7 +29,7 @@
typedef List<PopupMenuItem> PopupMenuItemsBuilder(NavigatorState navigator);
-class PopupMenu extends StatefulComponent {
+class PopupMenu extends StatelessComponent {
PopupMenu({
Key key,
this.items,
@@ -46,76 +46,46 @@
final NavigatorState navigator;
final PerformanceView performance;
- PopupMenuState createState() => new PopupMenuState();
-}
-
-class PopupMenuState extends State<PopupMenu> {
- void initState() {
- super.initState();
- config.performance.addListener(_performanceChanged);
- }
-
- void didUpdateConfig(PopupMenu 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 changed, and our state is tied up with the performance
- });
- }
-
- BoxPainter _painter;
-
- void _updateBoxPainter(BoxDecoration decoration) {
- if (_painter == null || _painter.decoration != decoration)
- _painter = new BoxPainter(decoration);
- }
-
Widget build(BuildContext context) {
- _updateBoxPainter(new BoxDecoration(
+ final BoxPainter painter = new BoxPainter(new BoxDecoration(
backgroundColor: Theme.of(context).canvasColor,
borderRadius: 2.0,
- boxShadow: shadows[config.level]
+ boxShadow: shadows[level]
));
- double unit = 1.0 / (config.items.length + 1.5); // 1.0 for the width and 0.5 for the last item's fade.
+
+ double unit = 1.0 / (items.length + 1.5); // 1.0 for the width and 0.5 for the last item's fade.
List<Widget> children = [];
- for (int i = 0; i < config.items.length; ++i) {
+
+ for (int i = 0; i < items.length; ++i) {
double start = (i + 1) * unit;
double end = (start + 1.5 * unit).clamp(0.0, 1.0);
children.add(new FadeTransition(
- performance: config.performance,
- opacity: new AnimatedValue<double>(0.0, end: 1.0, interval: new Interval(start, end)),
+ performance: performance,
+ opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(start, end)),
child: new InkWell(
- onTap: () { config.navigator.pop(config.items[i].value); },
- child: config.items[i]
+ onTap: () { navigator.pop(items[i].value); },
+ child: items[i]
))
);
}
- final width = new AnimatedValue<double>(0.0, end: 1.0, interval: new Interval(0.0, unit));
- final height = new AnimatedValue<double>(0.0, end: 1.0, interval: new Interval(0.0, unit * config.items.length));
+
+ final width = new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(0.0, unit));
+ final height = new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(0.0, unit * items.length));
+
return new FadeTransition(
- performance: config.performance,
- opacity: new AnimatedValue<double>(0.0, end: 1.0, interval: new Interval(0.0, 1.0 / 3.0)),
+ performance: performance,
+ opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: new Interval(0.0, 1.0 / 3.0)),
child: new Container(
margin: new EdgeDims.all(_kMenuMargin),
child: new BuilderTransition(
- performance: config.performance,
+ performance: performance,
variables: [width, height],
builder: (BuildContext context) {
return new CustomPaint(
callback: (sky.Canvas canvas, Size size) {
double widthValue = width.value * size.width;
double heightValue = height.value * size.height;
- _painter.paint(canvas, new Rect.fromLTWH(size.width - widthValue, 0.0, widthValue, heightValue));
+ painter.paint(canvas, new Rect.fromLTWH(size.width - widthValue, 0.0, widthValue, heightValue));
},
child: new ConstrainedBox(
constraints: new BoxConstraints(
@@ -162,7 +132,7 @@
Performance createPerformance() {
Performance result = super.createPerformance();
AnimationTiming timing = new AnimationTiming();
- timing.reverseInterval = new Interval(0.0, _kMenuCloseIntervalEnd);
+ timing.reverseCurve = new Interval(0.0, _kMenuCloseIntervalEnd);
result.timing = timing;
return result;
}