EffectController constructor
- double? duration,
- double? speed,
- Curve curve = Curves.linear,
- double? reverseDuration,
- double? reverseSpeed,
- Curve? reverseCurve,
- bool infinite = false,
- bool alternate = false,
- int? repeatCount,
- double startDelay = 0.0,
- double atMaxDuration = 0.0,
- double atMinDuration = 0.0,
- VoidCallback? onMax,
- VoidCallback? onMin,
Factory function for producing common EffectControllers.
In the simplest case, when only duration is provided, this will return
a LinearEffectController that grows linearly from 0 to 1 over the period
of that duration.
More generally, the produced effect controller allows to add a delay
before the beginning of the animation, to animate both forward and in
reverse, to iterate several times (or infinitely), to apply an arbitrary
curve making the effect progression non-linear, etc.
In the most general case, the animation proceeds through the following steps:
- wait for
startDelayseconds, - repeat the following steps
repeatCounttimes (orinfinitely): a. progress from 0 to 1 over thedurationseconds, b. wait foratMaxDurationseconds, c. progress from 1 to 0 over thereverseDurationseconds, d. wait foratMinDurationseconds.
Setting parameter alternate to true is another way to create a
controller whose reverseDuration is the same as the forward duration.
As an alternative to specifying durations, you can also provide speed
and reverseSpeed parameters, but only for effects where the notion of
a speed is well-defined (MeasurableEffects).
If the animation is finite and there are no "backward" or "atMin" stages
then the animation will complete at progress == 1, otherwise it will
complete at progress == 0.
Before atMaxDuration and atMinDuration a callback function can be
provided which will be called after the corresponding progress has
finished.
Implementation
factory EffectController({
double? duration,
double? speed,
Curve curve = Curves.linear,
double? reverseDuration,
double? reverseSpeed,
Curve? reverseCurve,
bool infinite = false,
bool alternate = false,
int? repeatCount,
double startDelay = 0.0,
double atMaxDuration = 0.0,
double atMinDuration = 0.0,
VoidCallback? onMax,
VoidCallback? onMin,
}) {
assert(
(duration ?? 1) >= 0,
'Duration cannot be negative: $duration',
);
assert(
(reverseDuration ?? 1) >= 0,
'Reverse duration cannot be negative: $reverseDuration',
);
assert(
(duration != null) || (speed != null),
'Either duration or speed must be specified',
);
assert(
!((duration != null || reverseDuration != null) &&
(speed != null || reverseSpeed != null)),
'Both duration and speed arguments cannot be specified at the same time',
);
assert(
(speed ?? 1) > 0,
'Speed must be positive: $speed',
);
assert(
(reverseSpeed ?? 1) > 0,
'Reverse speed must be positive: $reverseSpeed',
);
assert(
!(infinite && repeatCount != null),
'An infinite effect cannot have a repeat count',
);
assert(
(repeatCount ?? 1) > 0,
'Repeat count must be positive: $repeatCount',
);
assert(
startDelay >= 0,
'Start delay cannot be negative: $startDelay',
);
assert(
atMaxDuration >= 0,
'At-max duration cannot be negative: $atMaxDuration',
);
assert(
atMinDuration >= 0,
'At-min duration cannot be negative: $atMinDuration',
);
final items = <EffectController>[];
// FORWARD
final isLinear = curve == Curves.linear;
if (isLinear) {
items.add(
duration != null
? LinearEffectController(duration)
: SpeedEffectController(LinearEffectController(0), speed: speed!),
);
} else {
items.add(
duration != null
? CurvedEffectController(duration, curve)
: SpeedEffectController(
CurvedEffectController(1, curve),
speed: speed!,
),
);
}
// ON MAX CALLBACK
if (onMax != null) {
items.add(CallbackController(onMax, progress: 1.0));
}
// AT-MAX
if (atMaxDuration != 0) {
items.add(PauseEffectController(atMaxDuration, progress: 1.0));
}
// REVERSE
final hasReverse =
alternate || (reverseDuration != null) || (reverseSpeed != null);
if (hasReverse) {
final reverseIsLinear =
reverseCurve == Curves.linear || ((reverseCurve == null) && isLinear);
final reverseHasDuration =
(reverseDuration != null) ||
(reverseSpeed == null && duration != null);
if (reverseIsLinear) {
items.add(
reverseHasDuration
? ReverseLinearEffectController(reverseDuration ?? duration!)
: SpeedEffectController(
ReverseLinearEffectController(0),
speed: reverseSpeed ?? speed!,
),
);
} else {
reverseCurve ??= curve.flipped;
items.add(
reverseHasDuration
? ReverseCurvedEffectController(
reverseDuration ?? duration!,
reverseCurve,
)
: SpeedEffectController(
ReverseCurvedEffectController(1, reverseCurve),
speed: reverseSpeed ?? speed!,
),
);
}
}
// ON MIN CALLBACK
if (onMin != null) {
items.add(CallbackController(onMin, progress: 0.0));
}
// AT-MIN
if (atMinDuration != 0) {
items.add(PauseEffectController(atMinDuration, progress: 0.0));
}
assert(items.isNotEmpty);
var controller = items.length == 1
? items[0]
: SequenceEffectController(items);
if (infinite) {
controller = InfiniteEffectController(controller);
}
if (repeatCount != null && repeatCount != 1) {
controller = RepeatedEffectController(controller, repeatCount);
}
if (startDelay != 0) {
controller = DelayedEffectController(controller, delay: startDelay);
}
return controller;
}