I’m trying to create a text with an animation on hover, including a dot in front of it, using Flutter.
The design comes from this website (look at the bottom section you’ll find what I’m reproducing).
Here’s the code for my component:
import 'package:flutter/material.dart';
class MyText extends StatefulWidget {
final String text;
final TextStyle textStyle;
final double width;
final double underlineOffset;
final bool hasDot;
const MyText({
super.key,
required this.text,
required this.textStyle,
required this.width,
required this.underlineOffset,
this.hasDot = false,
});
@override
State<MyText> createState() => _MyTextState();
}
class _MyTextState extends State<MyText> with TickerProviderStateMixin {
late AnimationController _colorAnimationController;
late Animation _colorAnimation;
late AnimationController _underlineAnimationController;
late Animation _underlineAnimation;
@override
void initState() {
_colorAnimationController = AnimationController(
duration: const Duration(milliseconds: 250),
vsync: this,
)..addListener(() {
setState(() {});
});
_colorAnimation = ColorTween(
begin: Colors.black,
end: Colors.orange,
).animate(_colorAnimationController);
_underlineAnimationController = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
)..addListener(() {
if (_underlineAnimationController.isCompleted &&
_underlineAnimationController.value == 1) {
_underlineAnimationController.reset();
}
setState(() {});
});
_underlineAnimation = Tween(begin: -widget.width, end: widget.width)
.animate(_underlineAnimationController);
super.initState();
}
@override
Widget build(BuildContext context) {
return MouseRegion(
onEnter: (event) {
_colorAnimationController.forward();
_underlineAnimationController.animateTo(0.5);
},
onExit: (event) {
_colorAnimationController.reverse();
_underlineAnimationController.animateTo(1);
},
cursor: SystemMouseCursors.click,
child: ClipRRect(
child: Container(
alignment: Alignment.centerRight,
width: widget.hasDot ? widget.width + 25 : widget.width,
height: widget.underlineOffset + 2,
// color: Colors.green,
child: Stack(
clipBehavior: Clip.none,
children: [
// Points (si il y en a un)
if (widget.hasDot)
const Positioned(
top: 9,
left: -26,
child: Icon(
Icons.circle,
color: Colors.black,
size: 10,
),
),
// Texte
Stack(
children: [
Text(
widget.text,
style: widget.textStyle.copyWith(
color: _colorAnimation.value,
),
),
],
),
// Underline (onHover animation)
Positioned(
top: widget.underlineOffset,
left: _underlineAnimation.value,
child: Container(
width: widget.width,
height: 1,
color: Colors.orange,
),
)
],
),
),
),
);
}
}
It’s all working fine, but when I set hasDot: true
, the orange line appears under the dot.
Note: I want the underline animation to occur only under the text and not under the dot.
My issue is how to achieve the same animation effect as when hasDot
is false
, but with the dot included and the orange line hidden under the dot.
Additional info: If you need the full code of the Flutter project, please check my GitHub repo.
Thank you in advance for your help.
Have a great time coding!