Commit 3012cce1 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Clean up Tween and friends. (#9858)

parent a6eb0a3e
......@@ -47,7 +47,7 @@ class NavigationIconView {
return new FadeTransition(
opacity: _animation,
child: new SlideTransition(
position: new Tween<FractionalOffset>(
position: new FractionalOffsetTween(
begin: const FractionalOffset(0.0, 0.02), // Small offset from the top.
end: FractionalOffset.topLeft,
).animate(_animation),
......
......@@ -38,7 +38,7 @@ class _DrawerDemoState extends State<DrawerDemo> with TickerProviderStateMixin {
parent: new ReverseAnimation(_controller),
curve: Curves.fastOutSlowIn,
);
_drawerDetailsPosition = new Tween<FractionalOffset>(
_drawerDetailsPosition = new FractionalOffsetTween(
begin: const FractionalOffset(0.0, -1.0),
end: const FractionalOffset(0.0, 0.0),
).animate(new CurvedAnimation(
......
......@@ -24,9 +24,9 @@ enum AnimationStatus {
/// Signature for listeners attached using [Animation.addStatusListener].
typedef void AnimationStatusListener(AnimationStatus status);
/// An animation with a value of type T
/// An animation with a value of type `T`.
///
/// An animation consists of a value (of type T) together with a status. The
/// An animation consists of a value (of type `T`) together with a status. The
/// status indicates whether the animation is conceptually running from
/// beginning to end or from the end back to the beginning, although the actual
/// value of the animation might not change monotonically (e.g., if the
......
......@@ -2,7 +2,7 @@
// 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 'dart:ui' show Color, Size, Rect, hashValues;
import 'package:flutter/foundation.dart';
......@@ -10,7 +10,11 @@ import 'animation.dart';
import 'animations.dart';
import 'curves.dart';
/// An object that can produce a value of type T given an [Animation] as input.
/// An object that can produce a value of type `T` given an [Animation<double>]
/// as input.
///
/// Typically, the values of the input animation are nominally in the range 0.0
/// to 1.0. In principle, however, any value could be provided.
abstract class Animatable<T> {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
......@@ -77,14 +81,33 @@ class _ChainedEvaluation<T> extends Animatable<T> {
/// [Tween] is useful if you want to interpolate across a range.
///
/// To use a [Tween] object with an animation, call the [Tween] object's
/// `animate()` method and pass it the [Animation] object that you want to
/// [animate] method and pass it the [Animation] object that you want to
/// modify.
///
/// You can chain [Tween] objects together using the `chain()` method, so that a
/// You can chain [Tween] objects together using the [chain] method, so that a
/// single [Animation] object is configured by multiple [Tween] objects called
/// in succession. This is different than calling the `animate()` method twice,
/// in succession. This is different than calling the [animate] method twice,
/// which results in two [Animation] separate objects, each configured with a
/// single [Tween].
///
/// ## Sample usage
///
/// Suppose `_controller` is an [AnimationController], and we want to create an
/// [Animation<Offset>] that is controlled by that controller, and save it in
/// `_animation`:
///
/// ```dart
/// _animation = new Tween<Offset>(
/// begin: const Offset(100.0, 50.0),
/// end: const Offset(200.0, 300.0),
/// ).animation(_controller);
/// ```
///
/// That would provide an `_animation` that, over the lifetime of the
/// `_controller`'s animation, returns a value that depicts a point along the
/// line between the two offsets above. If we used a [MaterialPointArcTween]
/// instead of a [Tween<Offset>] in the code above, the points would follow a
/// pleasing curve instead of a straight line, with no other changes necessary.
class Tween<T extends dynamic> extends Animatable<T> {
/// Creates a tween.
///
......@@ -95,27 +118,38 @@ class Tween<T extends dynamic> extends Animatable<T> {
/// The value this variable has at the beginning of the animation.
///
/// Must be non-null before this [Tween] is evaluated.
/// See the constructor for details about whether this property may be null
/// (it varies from subclass to subclass).
T begin;
/// The value this variable has at the end of the animation.
///
/// Must be non-null before this [Tween] is evaluated.
/// See the constructor for details about whether this property may be null
/// (it varies from subclass to subclass).
T end;
/// Returns the value this variable has at the given animation clock value.
///
/// The [begin] and [end] properties must be non-null by the time this method
/// is called.
T lerp(double t) => begin + (end - begin) * t;
/// The default implementation of this method uses the [+], [-], and [*]
/// operators on `T`. The [begin] and [end] properties must therefore be
/// non-null by the time this method is called.
T lerp(double t) {
assert(begin != null);
assert(end != null);
return begin + (end - begin) * t;
}
/// Returns the interpolated value for the current value of the given animation.
///
/// This method returns `begin` and `end` when the animation values are 0.0 or
/// 1.0, respectively.
///
/// The [begin] and [end] properties must be non-null by the time this method
/// is called with an animation that is not at 0.0 or 1.0.
/// This function is implemented by deferring to [lerp]. Subclasses that want to
/// provide custom behavior should override [lerp], not [evaluate].
///
/// See the constructor for details about whether the [begin] and [end]
/// properties may be null when this is called. It varies from subclass to
/// subclass.
@override
T evaluate(Animation<double> animation) {
final double t = animation.value;
......@@ -126,67 +160,89 @@ class Tween<T extends dynamic> extends Animatable<T> {
return lerp(t);
}
@override
bool operator ==(dynamic other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
final Tween<T> typedOther = other;
return begin == typedOther.begin
&& end == typedOther.end;
}
@override
int get hashCode => hashValues(begin, end);
@override
String toString() => '$runtimeType($begin \u2192 $end)';
}
/// An interpolation between two colors.
///
/// This class specializes the interpolation of Tween<Color> to be
/// appropriate for colors.
/// This class specializes the interpolation of [Tween<Color>] to use
/// [Color.lerp].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class ColorTween extends Tween<Color> {
/// Creates a color tween.
/// Creates a [Color] tween.
///
/// The [begin] and [end] properties must be non-null before the tween is
/// first used, but the arguments can be null if the values are going to be
/// filled in later.
/// The [begin] and [end] properties may be null; the null value
/// is treated as transparent black.
ColorTween({ Color begin, Color end }) : super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
Color lerp(double t) => Color.lerp(begin, end, t);
}
/// An interpolation between two sizes.
///
/// This class specializes the interpolation of Tween<Size> to be
/// appropriate for rectangles.
/// This class specializes the interpolation of [Tween<Size>] to use
/// [Size.lerp].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class SizeTween extends Tween<Size> {
/// Creates a size tween.
/// Creates a [Size] tween.
///
/// The [begin] and [end] properties must be non-null before the tween is
/// first used, but the arguments can be null if the values are going to be
/// filled in later.
/// The [begin] and [end] properties may be null; the null value
/// is treated as an empty size.
SizeTween({ Size begin, Size end }) : super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
Size lerp(double t) => Size.lerp(begin, end, t);
}
/// An interpolation between two rectangles.
///
/// This class specializes the interpolation of Tween<Rect> to be
/// appropriate for rectangles.
/// This class specializes the interpolation of [Tween<Rect>] to use
/// [Rect.lerp].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class RectTween extends Tween<Rect> {
/// Creates a rect tween.
/// Creates a [Rect] tween.
///
/// The [begin] and [end] properties must be non-null before the tween is
/// first used, but the arguments can be null if the values are going to be
/// filled in later.
/// The [begin] and [end] properties may be null; the null value
/// is treated as an empty rect at the top left corner.
RectTween({ Rect begin, Rect end }) : super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
Rect lerp(double t) => Rect.lerp(begin, end, t);
}
/// An interpolation between two integers that rounds.
///
/// This class specializes the interpolation of Tween<int> to be
/// This class specializes the interpolation of [Tween<int>] to be
/// appropriate for integers by interpolating between the given begin
/// and end values and then rounding the result to the nearest
/// integer.
///
/// This is the closest approximation to a linear tween that is
/// possible with an integer. Compare to [StepTween].
/// This is the closest approximation to a linear tween that is possible with an
/// integer. Compare to [StepTween] and [Tween<double>].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class IntTween extends Tween<int> {
/// Creates an int tween.
///
......@@ -203,15 +259,17 @@ class IntTween extends Tween<int> {
/// An interpolation between two integers that floors.
///
/// This class specializes the interpolation of Tween<int> to be
/// This class specializes the interpolation of [Tween<int>] to be
/// appropriate for integers by interpolating between the given begin
/// and end values and then using [int.floor()] to return the current
/// and end values and then using [int.floor] to return the current
/// integer component, dropping the fractional component.
///
/// This results in a value that is never greater than the equivalent
/// value from a linear double interpolation. Compare to [IntTween].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class StepTween extends Tween<int> {
/// Creates a step tween.
/// Creates an [int] tween that floors.
///
/// The [begin] and [end] properties must be non-null before the tween is
/// first used, but the arguments can be null if the values are going to be
......
This diff is collapsed.
......@@ -129,9 +129,18 @@ class Theme extends InheritedWidget {
}
}
/// An animated value that interpolates [ThemeData]s.
/// An interpolation between two [ThemeData]s.
///
/// This class specializes the interpolation of [Tween<ThemeData>] to call the
/// [ThemeData.lerp] method.
///
/// See [Tween] for a discussion on how to use interpolation objects.
class ThemeDataTween extends Tween<ThemeData> {
/// Creates an interpolation between [begin] and [end].
/// Creates a [ThemeData] tween.
///
/// The [begin] and [end] properties must be non-null before the tween is
/// first used, but the arguments can be null if the values are going to be
/// filled in later.
ThemeDataTween({ ThemeData begin, ThemeData end }) : super(begin: begin, end: end);
@override
......
......@@ -441,7 +441,11 @@ class ThemeData {
}
/// Linearly interpolate between two themes.
///
/// The arguments must not be null.
static ThemeData lerp(ThemeData begin, ThemeData end, double t) {
assert(begin != null);
assert(end != null);
return new ThemeData.raw(
brightness: t < 0.5 ? begin.brightness : end.brightness,
primaryColor: Color.lerp(begin.primaryColor, end.primaryColor, t),
......
......@@ -9,13 +9,17 @@ import 'package:flutter/painting.dart';
///
/// This class specializes the interpolation of Tween<FractionalOffset> to be
/// appropriate for rectangles.
///
/// See [Tween] for a discussion on how to use interpolation objects.
class FractionalOffsetTween extends Tween<FractionalOffset> {
/// Creates a fractional offset tween.
///
/// The [begin] and [end] arguments must not be null.
/// The [begin] and [end] properties may be null; the null value
/// is treated as meaning the top left corner.
FractionalOffsetTween({ FractionalOffset begin, FractionalOffset end })
: super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
FractionalOffset lerp(double t) => FractionalOffset.lerp(begin, end, t);
}
......@@ -265,7 +265,7 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
}
void _updateMoveAnimation() {
_moveAnimation = new Tween<FractionalOffset>(
_moveAnimation = new FractionalOffsetTween(
begin: FractionalOffset.topLeft,
end: _directionIsXAxis ?
new FractionalOffset(_dragExtent.sign, 0.0) :
......
......@@ -13,60 +13,104 @@ import 'text.dart';
import 'ticker_provider.dart';
/// An interpolation between two [BoxConstraints].
///
/// This class specializes the interpolation of [Tween<BoxConstraints>] to use
/// [BoxConstraints.lerp].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class BoxConstraintsTween extends Tween<BoxConstraints> {
/// Creates a box constraints tween.
/// Creates a [BoxConstraints] tween.
///
/// The [begin] and [end] arguments must not be null.
/// The [begin] and [end] properties may be null; the null value
/// is treated as a tight constraint of zero size.
BoxConstraintsTween({ BoxConstraints begin, BoxConstraints end }) : super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
BoxConstraints lerp(double t) => BoxConstraints.lerp(begin, end, t);
}
/// An interpolation between two [Decoration]s.
///
/// This class specializes the interpolation of [Tween<BoxConstraints>] to use
/// [Decoration.lerp].
///
/// Typically this will only have useful results if the [begin] and [end]
/// decorations have the same type; decorations of differing types generally do
/// not have a useful animation defined, and will just jump to the [end]
/// immediately.
///
/// See [Tween] for a discussion on how to use interpolation objects.
class DecorationTween extends Tween<Decoration> {
/// Creates a decoration tween.
///
/// The [begin] and [end] arguments must not be null.
/// The [begin] and [end] properties may be null. If both are null, then the
/// result is always null. If [end] is not null, then its lerping logic is
/// used (via [Decoration.lerpTo]). Otherwise, [begin]'s lerping logic is used
/// (via [Decoration.lerpFrom]).
DecorationTween({ Decoration begin, Decoration end }) : super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
Decoration lerp(double t) => Decoration.lerp(begin, end, t);
}
/// An interpolation between two [EdgeInsets]s.
///
/// This class specializes the interpolation of [Tween<EdgeInsets>] to use
/// [EdgeInsets.lerp].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class EdgeInsetsTween extends Tween<EdgeInsets> {
/// Creates an edge insets tween.
/// Creates an [EdgeInsets] tween.
///
/// The [begin] and [end] arguments must not be null.
/// The [begin] and [end] properties may be null; the null value
/// is treated as an [EdgeInsets] with no inset.
EdgeInsetsTween({ EdgeInsets begin, EdgeInsets end }) : super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
EdgeInsets lerp(double t) => EdgeInsets.lerp(begin, end, t);
}
/// An interpolation between two [BorderRadius]s.
///
/// This class specializes the interpolation of [Tween<BorderRadius>] to use
/// [BorderRadius.lerp].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class BorderRadiusTween extends Tween<BorderRadius> {
/// Creates a border radius tween.
/// Creates a [BorderRadius] tween.
///
/// The [begin] and [end] arguments must not be null.
/// The [begin] and [end] properties may be null; the null value
/// is treated as a right angle (no radius).
BorderRadiusTween({ BorderRadius begin, BorderRadius end }) : super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
BorderRadius lerp(double t) => BorderRadius.lerp(begin, end, t);
}
/// An interpolation between two [Matrix4]s.
///
/// This class specializes the interpolation of [Tween<Matrix4>] to be
/// appropriate for transformation matrices.
///
/// Currently this class works only for translations.
///
/// See [Tween] for a discussion on how to use interpolation objects.
class Matrix4Tween extends Tween<Matrix4> {
/// Creates a [Matrix4] tween.
///
/// The [begin] and [end] arguments must not be null.
/// The [begin] and [end] properties must be non-null before the tween is
/// first used, but the arguments can be null if the values are going to be
/// filled in later.
Matrix4Tween({ Matrix4 begin, Matrix4 end }) : super(begin: begin, end: end);
@override
Matrix4 lerp(double t) {
assert(begin != null);
assert(end != null);
// TODO(abarth): We should use [Matrix4.decompose] and animate the
// decomposed parameters instead of just animating the translation.
final Vector3 beginT = begin.getTranslation();
......@@ -78,13 +122,21 @@ class Matrix4Tween extends Tween<Matrix4> {
/// An interpolation between two [TextStyle]s.
///
/// This class specializes the interpolation of [Tween<TextStyle>] to use
/// [TextStyle.lerp].
///
/// This will not work well if the styles don't set the same fields.
///
/// See [Tween] for a discussion on how to use interpolation objects.
class TextStyleTween extends Tween<TextStyle> {
/// Creates a text style tween.
///
/// The [begin] and [end] arguments must not be null.
/// The [begin] and [end] properties must be non-null before the tween is
/// first used, but the arguments can be null if the values are going to be
/// filled in later.
TextStyleTween({ TextStyle begin, TextStyle end }) : super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
TextStyle lerp(double t) => TextStyle.lerp(begin, end, t);
}
......
......@@ -293,16 +293,19 @@ class FadeTransition extends AnimatedWidget {
/// An interpolation between two relative rects.
///
/// This class specializes the interpolation of Tween<RelativeRect> to be
/// appropriate for rectangles that are described in terms of offsets from
/// other rectangles.
/// This class specializes the interpolation of [Tween<RelativeRect>] to
/// use [RelativeRect.tween].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class RelativeRectTween extends Tween<RelativeRect> {
/// Creates a relative rect tween.
/// Creates a [RelativeRect] tween.
///
/// The [begin] and [end] arguments must not be null.
/// The [begin] and [end] properties may be null; the null value
/// is treated as [RelativeRect.fill].
RelativeRectTween({ RelativeRect begin, RelativeRect end })
: super(begin: begin, end: end);
/// Returns the value this variable has at the given animation clock value.
@override
RelativeRect lerp(double t) => RelativeRect.lerp(begin, end, t);
}
......
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