import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import '../../../core/utils/size_config.dart'; class AnimatedFeedbackButton extends StatefulWidget { final String iconPath; final Color activeColor; final Color inactiveColor; final bool isActive; final VoidCallback onTap; final String tooltip; const AnimatedFeedbackButton({ required this.iconPath, required this.activeColor, required this.inactiveColor, required this.isActive, required this.onTap, required this.tooltip, super.key, }); @override State createState() => _AnimatedFeedbackButtonState(); } class _AnimatedFeedbackButtonState extends State with TickerProviderStateMixin { late AnimationController _clickController; late Animation _scaleAnimation; late Animation _rotationAnimation; @override void initState() { super.initState(); _clickController = AnimationController( duration: const Duration(milliseconds: 250), vsync: this, ); _scaleAnimation = Tween(begin: 1.0, end: 1.2).animate( CurvedAnimation( parent: _clickController, curve: const Interval(0.0, 0.3, curve: Curves.elasticOut), reverseCurve: const Interval(0.0, 0.3, curve: Curves.elasticOut), ), ); _rotationAnimation = Tween(begin: 0.0, end: -0.15).animate( CurvedAnimation( parent: _clickController, curve: const Interval(0.0, 0.1, curve: Curves.elasticOut), reverseCurve: const Interval(0.0, 0.1, curve: Curves.elasticOut), ), ); } @override void dispose() { _clickController.dispose(); super.dispose(); } void _handleTap() { _clickController.forward().then((_) { _clickController.reverse(); }); widget.onTap(); } @override Widget build(BuildContext context) { return Tooltip( message: widget.tooltip, child: InkWell( splashColor: Colors.transparent, onTap: _handleTap, child: AnimatedBuilder( animation: _clickController, builder: (context, child) { return Transform.scale( scale: _scaleAnimation.value, child: Transform.rotate( angle: _rotationAnimation.value, child: TweenAnimationBuilder( tween: ColorTween( begin: widget.inactiveColor, end: widget.isActive ? widget.activeColor : widget.inactiveColor, ), duration: const Duration(milliseconds: 100), curve: Curves.easeInOut, builder: (context, color, child) { return SvgPicture.asset( width: 24.0.w(), height: 24.0.w(), fit: BoxFit.cover, widget.iconPath, colorFilter: ColorFilter.mode( color ?? widget.inactiveColor, BlendMode.srcATop, ), ); }, ), ), ); }, ), ), ); } }