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
startDelay
seconds, - repeat the following steps
repeatCount
times (orinfinite
ly): a. progress from 0 to 1 over theduration
seconds, b. wait foratMaxDuration
seconds, c. progress from 1 to 0 over thereverseDuration
seconds, d. wait foratMinDuration
seconds.
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 (MeasurableEffect
s).
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 && speed != null),
'Both duration and speed cannot be specified at the same time',
);
assert(
!(reverseDuration != null && reverseSpeed != null),
'Both reverseDuration and reverseSpeed 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;
}