Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.4"
lints:
dependency: transitive
description:
Expand Down Expand Up @@ -162,14 +155,14 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.14"
version: "0.4.12"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
version: "2.1.2"
sdks:
dart: ">=2.18.0 <3.0.0"
dart: ">=2.17.1 <3.0.0"
flutter: ">=1.17.0"
7 changes: 2 additions & 5 deletions lib/animate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ class Animate extends StatefulWidget with AnimateManager<Animate> {
EffectEntry? prior = _lastEntry;

Duration delay = (effect is ThenEffect)
? (effect.delay ?? Duration.zero) +
(prior?.delay ?? Duration.zero) +
(prior?.duration ?? Duration.zero)
? (effect.delay ?? Duration.zero) + (prior?.delay ?? Duration.zero) + (prior?.duration ?? Duration.zero)
: effect.delay ?? prior?.delay ?? Duration.zero;

EffectEntry entry = EffectEntry(
Expand Down Expand Up @@ -205,8 +203,7 @@ class _AnimateState extends State<Animate> with SingleTickerProviderStateMixin {

@override
void didUpdateWidget(Animate oldWidget) {
if (oldWidget.controller != widget.controller ||
oldWidget._duration != widget._duration) {
if (oldWidget.controller != widget.controller || oldWidget._duration != widget._duration) {
_initController();
_play();
} else if (oldWidget.adapter != widget.adapter) {
Expand Down
3 changes: 1 addition & 2 deletions lib/animate_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ import 'flutter_animate.dart';
/// )
/// )
/// ```
class AnimateList<T extends Widget> extends ListBase<Widget>
with AnimateManager<AnimateList> {
class AnimateList<T extends Widget> extends ListBase<Widget> with AnimateManager<AnimateList> {
/// Specifies a default interval to use for new `AnimateList` instances.
static Duration defaultInterval = Duration.zero;

Expand Down
64 changes: 44 additions & 20 deletions lib/effects/effect.dart → lib/effect.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import '../flutter_animate.dart';
import 'flutter_animate.dart';

/// Used to easily create effects that are composed of one or more existing Effects. Provides
/// syntactic sugar for overrideing build and calling the `composeEffects` method
/// with a list of effects.
mixin CompositeEffectMixin on Effect {
List<Effect> get effects;

@override
Widget build(BuildContext context, Widget child, AnimationController controller, EffectEntry entry) =>
composeEffects(effects, context, child, controller, entry);
}

/// Adds a begin/end fields and a convenience method for passing them to entry.buildAnimation()
class BeginEndEffect<T> extends Effect {
const BeginEndEffect({super.delay, super.duration, super.curve, this.begin, this.end});

/// The begin value for the effect. If null, effects should use a reasonable
/// default value when appropriate.
final T? begin;

/// The end value for the effect. If null, effects should use a reasonable
/// default value when appropriate.
final T? end;

/// Helper method for concrete effects to easily create an Animation<T> from the current begin/end values.
Animation<T> buildBeginEndAnimation(AnimationController controller, EffectEntry entry) =>
entry.buildTweenedAnimation(controller, Tween(begin: begin, end: end));
}

/// Class that defines the required interface and helper methods for
/// all effect classes. Look at the various effects for examples of how
Expand All @@ -9,7 +37,9 @@ import '../flutter_animate.dart';
///
/// It can be instantiated and added to Animate, but has no visual effect.
@immutable
class Effect<T> {
class Effect {
const Effect({this.delay, this.duration, this.curve});

/// The specified delay for the effect. If null, will use the delay from the
/// previous effect, or [Duration.zero] if this is the first effect.
final Duration? delay;
Expand All @@ -22,16 +52,6 @@ class Effect<T> {
/// previous effect, or [Animate.defaultCurve] if this is the first effect.
final Curve? curve;

/// The begin value for the effect. If null, effects should use a reasonable
/// default value when appropriate.
final T? begin;

/// The end value for the effect. If null, effects should use a reasonable
/// default value when appropriate.
final T? end;

const Effect({this.delay, this.duration, this.curve, this.begin, this.end});

/// Builds the widgets necessary to implement the effect, based on the
/// provided [AnimationController] and [EffectEntry].
Widget build(
Expand All @@ -43,14 +63,19 @@ class Effect<T> {
return child;
}

/// Returns an animation based on the controller, entry, and begin/end values.
Animation<T> buildAnimation(
/// Calls build on one or more effects, composing them together and returning the resulting widget tree.
@protected
Widget composeEffects(
List<Effect> effects,
BuildContext context,
Widget child,
AnimationController controller,
EffectEntry entry,
) {
return entry
.buildAnimation(controller)
.drive(Tween<T>(begin: begin, end: end));
for (var f in effects) {
child = f.build(context, child, controller, entry);
}
return child;
}

/// Returns a ratio corresponding to the beginning of the specified entry.
Expand All @@ -68,8 +93,7 @@ class Effect<T> {
/// Check if the animation is currently running / active.
bool isAnimationActive(Animation animation) {
AnimationStatus status = animation.status;
return status == AnimationStatus.forward ||
status == AnimationStatus.reverse;
return status == AnimationStatus.forward || status == AnimationStatus.reverse;
}

/// Returns an optimized [AnimatedBuilder] that doesn't
Expand Down Expand Up @@ -117,7 +141,7 @@ extension EffectExtensions<T> on AnimateManager<T> {
double? begin,
double? end,
}) =>
addEffect(Effect(
addEffect(BeginEndEffect(
delay: delay,
duration: duration,
curve: curve,
Expand Down
59 changes: 59 additions & 0 deletions lib/effect_entry.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_animate/flutter_animate.dart';

export 'animate.dart';
export 'animate_list.dart';
export 'adapters/adapters.dart';
export 'effects/effects.dart';

export 'extensions/extensions.dart';

/// Because [Effect] classes are immutable and may be reused between multiple
/// [Animate] (or [AnimateList]) instances, an `EffectEntry` is created to store
/// values that may be different between instances. For example, due to
/// `AnimateList interval`, or from inheriting values from prior effects in the chain.
@immutable
class EffectEntry {
const EffectEntry({
required this.effect,
required this.delay,
required this.duration,
required this.curve,
required this.owner,
});

/// The delay for this entry.
final Duration delay;

/// The duration for this entry.
final Duration duration;

/// The curve used by this entry.
final Curve curve;

/// The effect associated with this entry.
final Effect effect;

/// The [Animate] instance that created this entry. This can be used by effects
/// to read information about the animation. Effects _should not_ modify
/// the animation (ex. by calling [Animate.addEffect]).
final Animate owner;

/// The begin time for this entry.
Duration get begin => delay;

/// The end time for this entry.
Duration get end => delay + duration;

/// Builds a sub-animation that runs from 0-1, based on the properties of this entry.
Animation<double> buildAnimation(
AnimationController controller, {
Curve? curve,
}) {
return buildSubAnimation(controller, begin, end, curve ?? this.curve);
}

/// Builds an sub-animation that runs from the begin and end values of a given [Tween]
Animation<T> buildTweenedAnimation<T>(AnimationController controller, Tween<T> tween) =>
buildAnimation(controller).drive(tween);
}
4 changes: 2 additions & 2 deletions lib/effects/blur_effect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import '../flutter_animate.dart';
/// Effect that animates a blur on the target (via [ImageFiltered])
/// between the specified begin and end blur radius values. Defaults to a blur radius of `begin=0, end=4`.
@immutable
class BlurEffect extends Effect<Offset> {
class BlurEffect extends BeginEndEffect<Offset> {
static const Offset neutralValue = Offset(neutralBlur, neutralBlur);
static const Offset defaultValue = Offset(defaultBlur, defaultBlur);

Expand Down Expand Up @@ -35,7 +35,7 @@ class BlurEffect extends Effect<Offset> {
AnimationController controller,
EffectEntry entry,
) {
Animation<Offset> animation = buildAnimation(controller, entry);
Animation<Offset> animation = buildBeginEndAnimation(controller, entry);
return getOptimizedBuilder<Offset>(
animation: animation,
builder: (_, __) {
Expand Down
2 changes: 1 addition & 1 deletion lib/effects/callback_effect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import '../flutter_animate.dart';
/// an animation that is driven by an [Adapter] (or manipulated via its controller)
/// may behave unexpectedly in certain circumstances.
@immutable
class CallbackEffect extends Effect<void> {
class CallbackEffect extends Effect {
const CallbackEffect({
Duration? delay,
Duration? duration,
Expand Down
6 changes: 3 additions & 3 deletions lib/effects/custom_effect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import '../flutter_animate.dart';
/// ```
///
/// Note that the above could also be accomplished by creating a custom effect class
/// that extends [Effect] and utilizes [AnimatedPadding].
/// that extends [BeginEndEffect] and utilizes [AnimatedPadding].
@immutable
class CustomEffect extends Effect<double> {
class CustomEffect extends BeginEndEffect<double> {
const CustomEffect({
required this.builder,
Duration? delay,
Expand All @@ -38,7 +38,7 @@ class CustomEffect extends Effect<double> {
AnimationController controller,
EffectEntry entry,
) {
Animation<double> animation = buildAnimation(controller, entry);
Animation<double> animation = buildBeginEndAnimation(controller, entry);
return getOptimizedBuilder<double>(
animation: animation,
builder: (ctx, __) => builder(ctx, animation.value, child),
Expand Down
6 changes: 4 additions & 2 deletions lib/effects/effects.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// collects effect classes for easy import.
export 'effect.dart';

export 'blur_effect.dart';
export 'callback_effect.dart';
export 'custom_effect.dart';
Expand All @@ -19,3 +17,7 @@ export 'then_effect.dart';
export 'tint_effect.dart';
export 'toggle_effect.dart';
export 'visibility_effect.dart';
export 'variations/fade_in.dart';
export 'variations/fade_out.dart';
export 'variations/slide_in.dart';
export 'variations/slide_out.dart';
36 changes: 2 additions & 34 deletions lib/effects/fade_effect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import '../flutter_animate.dart';
/// Effect that animates the opacity of the target (via [FadeTransition]) between the specified begin and end values.
/// It defaults to `begin=0, end=1`.
@immutable
class FadeEffect extends Effect<double> {
class FadeEffect extends BeginEndEffect<double> {
static const double neutralValue = 1.0;
static const double defaultValue = 0.0;

Expand All @@ -31,7 +31,7 @@ class FadeEffect extends Effect<double> {
EffectEntry entry,
) {
return FadeTransition(
opacity: buildAnimation(controller, entry),
opacity: buildBeginEndAnimation(controller, entry),
child: child,
);
}
Expand All @@ -53,36 +53,4 @@ extension FadeEffectExtensions<T> on AnimateManager<T> {
begin: begin,
end: end,
));

/// Adds a [fadeIn] extension to [AnimateManager] ([Animate] and [AnimateList]).
/// This is identical to the [fade] extension, except it always uses `end=1.0`.
T fadeIn({
Duration? delay,
Duration? duration,
Curve? curve,
double? begin,
}) =>
addEffect(FadeEffect(
delay: delay,
duration: duration,
curve: curve,
begin: begin ?? FadeEffect.defaultValue,
end: 1.0,
));

/// Adds a [fadeOut] extension to [AnimateManager] ([Animate] and [AnimateList]).
/// This is identical to the [fade] extension, except it always uses `end=0.0`.
T fadeOut({
Duration? delay,
Duration? duration,
Curve? curve,
double? begin,
}) =>
addEffect(FadeEffect(
delay: delay,
duration: duration,
curve: curve,
begin: begin ?? FadeEffect.neutralValue,
end: 0.0,
));
}
4 changes: 2 additions & 2 deletions lib/effects/flip_effect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import '../flutter_animate.dart';
/// would cause it to rotate around the Y axis — flipping horizontally.
/// Default is [Axis.vertical].
@immutable
class FlipEffect extends Effect<double> {
class FlipEffect extends BeginEndEffect<double> {
static const double neutralValue = 0.0;
static const double defaultValue = -0.5;

Expand Down Expand Up @@ -60,7 +60,7 @@ class FlipEffect extends Effect<double> {
AnimationController controller,
EffectEntry entry,
) {
Animation<double> animation = buildAnimation(controller, entry);
Animation<double> animation = buildBeginEndAnimation(controller, entry);
return getOptimizedBuilder<double>(
animation: animation,
builder: (_, __) {
Expand Down
2 changes: 1 addition & 1 deletion lib/effects/listen_effect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import '../flutter_animate.dart';
///
/// See also: [CustomEffect] and [CallbackEffect].
@immutable
class ListenEffect extends Effect<double> {
class ListenEffect extends BeginEndEffect<double> {
const ListenEffect({
Duration? delay,
Duration? duration,
Expand Down
4 changes: 2 additions & 2 deletions lib/effects/move_effect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import '../flutter_animate.dart';
///
/// To specify offsets relative to the target's size, use [SlideEffect].
@immutable
class MoveEffect extends Effect<Offset> {
class MoveEffect extends BeginEndEffect<Offset> {
static const Offset neutralValue = Offset(neutralMove, neutralMove);
static const Offset defaultValue = Offset(neutralMove, defaultMove);

Expand Down Expand Up @@ -41,7 +41,7 @@ class MoveEffect extends Effect<Offset> {
AnimationController controller,
EffectEntry entry,
) {
Animation<Offset> animation = buildAnimation(controller, entry);
Animation<Offset> animation = buildBeginEndAnimation(controller, entry);
return getOptimizedBuilder<Offset>(
animation: animation,
builder: (_, __) {
Expand Down
Loading