Skip to content

Instantly share code, notes, and snippets.

@CoderNamedHendrick
Last active November 30, 2022 14:13
Show Gist options
  • Save CoderNamedHendrick/54bc5ba0626a1bf8d4b06a87583a1d49 to your computer and use it in GitHub Desktop.
Save CoderNamedHendrick/54bc5ba0626a1bf8d4b06a87583a1d49 to your computer and use it in GitHub Desktop.
Cleaner impl.
class AnimatingIcon extends StatefulWidget {
const AnimatingIcon({super.key, this.onTap});
final VoidCallback? onTap;
@override
State<AnimatingIcon> createState() => _AnimatingIconState();
}
class _AnimatingIconState extends State<AnimatingIcon>
with SingleTickerProviderStateMixin {
late final AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 850));
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reset();
}
if (status == AnimationStatus.dismissed) {
_controller.forward();
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (_controller.isAnimating) {
_controller.reset();
_controller.stop();
} else {
_controller.forward();
}
widget.onTap?.call();
},
child: MicAnimatingIcon(controller: _controller),
);
}
}
class MicAnimatingIcon extends AnimatedWidget {
final AnimationController controller;
static const startSize = 100.0;
static const endSize = 50.0;
const MicAnimatingIcon({super.key, required this.controller})
: super(listenable: controller);
Animation<double> get _sizeStep =>
_StepTween(startSize: startSize, endSize: endSize).animate(controller);
Animation<double> get _iconStep =>
_StepTween(startSize: startSize / 3, endSize: endSize / 2)
.animate(controller);
Animation<double> get _sizeStepTwo =>
Tween<double>(begin: startSize, end: endSize)
.animate(CurvedAnimation(parent: controller, curve: _StepCurveTwo()));
@override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.loose,
clipBehavior: Clip.none,
alignment: AlignmentDirectional.center,
children: [
Container(
height: startSize,
width: startSize,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
),
Container(
height: _sizeStepTwo.value,
width: _sizeStepTwo.value,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.green,
boxShadow: [
if (_sizeStepTwo.value >= 0.5)
const BoxShadow(
color: Colors.black38,
offset: Offset(-1, 1),
blurRadius: 5,
spreadRadius: 0.6),
]),
),
Container(
height: _sizeStep.value,
width: _sizeStep.value,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.purple[400],
),
alignment: Alignment.center,
child: Icon(
Icons.mic,
color: Colors.white,
size: _iconStep.value,
),
),
],
);
}
}
class _StepTween extends Tween<double> {
final double startSize;
final double endSize;
_StepTween({required this.startSize, required this.endSize})
: super(begin: startSize, end: endSize);
@override
double lerp(double t) {
if (t < 0.33) {
return lerpDouble(startSize, endSize, 0) ?? 0;
}
if (t > 0.65) {
return lerpDouble(startSize, endSize, 1) ?? 0;
}
return lerpDouble(startSize, endSize, 0.5) ?? 0;
}
}
class _StepCurveTwo extends Curve {
@override
double transformInternal(double t) {
if (t < 0.65) {
return 0;
}
return 0.5;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment