I'm developing a countdown timer, and I needed to be able to make it flash on-and-off when it gets to a certain point. There's slightly more to it than simply a text widget like the one pictured; so existing packages for blinking text didn't quite fit the bill.
That's why I built Flasher; a tiny Flutter package for flashing its whild widget on-and-off.
It's fully configurable:
- You can adjust the time between "flashes", and the duration of the flash
- You can have it run indefinitely, or a finite number of times
- You can have the widget fade out, if you need to hide it after it's finished
- You can configure how long it takes to fade out, as well as wait for a configurable amount of time before it does so
How to Use it
Import the package:
import 'package:flasher/flasher.dart';
Here's a minimal example:
Flasher(
child: Text('Blink'),
)
This repeats indefinitely; to limit it use repeat
; for example, to flash ten times:
Flasher(
repeat: 10,
child: Text('Blink'),
)
By default, once it's finished flashing it will remain visible.
Alternatively, you can tell it to fade out afterwards, after a short delay:
Flasher.fadeOutAfter(
fadeOutDuration = const Duration(milliseconds: 350),
fadeOutDelay = const Duration(milliseconds: 150,),
repeat: 10,
child: Text('I fade out')
)
Full documentation is available on Github.
How it Works
The main animation uses a tween sequence, with two stages.
The first is a ConstantTween
:
ConstantTween<double>(1.0)
Here, the number represents the opacity; in other words, at this stage in the animation it's fully visible. The wait between flashes, if you will.
Then it performs the "flash":
Tween<double>(begin: 1.0, end: 0)
Tween sequences require a weight to know when to move from one tween to another; this is basically a percentage of its runtime. By calculating a percentage that represents how long it's fully visible, and another for when it's flashing, the seuqnce can be built dynamically like this:
final Animatable<double> tweenSequence = TweenSequence<double>(
<TweenSequenceItem<double>>[
TweenSequenceItem<double>(
tween: ConstantTween<double>(1.0),
weight: visiblePc,
),
TweenSequenceItem<double>(
tween: Tween<double>(begin: 1.0, end: 0)
.chain(CurveTween(curve: widget.curve)),
weight: flashPc,
),
],
);
I won't paste the whole thing in; but essentially it registers a listener for when the animation completes; i.e., flashes a single time. Then based on whether it's been configured to flash a finite number of times and an internal counter, it determines whether or not it should replay the animation.
If it hasn't been configured to fade out, it simply stops at this point. Otherwise, another animation gets triggered to fade it out.
I plan to make it available on pub.dev soon.