117 lines
3.3 KiB
Dart
117 lines
3.3 KiB
Dart
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<AnimatedFeedbackButton> createState() => _AnimatedFeedbackButtonState();
|
|
}
|
|
|
|
class _AnimatedFeedbackButtonState extends State<AnimatedFeedbackButton>
|
|
with TickerProviderStateMixin {
|
|
late AnimationController _clickController;
|
|
late Animation<double> _scaleAnimation;
|
|
late Animation<double> _rotationAnimation;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_clickController = AnimationController(
|
|
duration: const Duration(milliseconds: 250),
|
|
vsync: this,
|
|
);
|
|
|
|
_scaleAnimation = Tween<double>(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<double>(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<Color?>(
|
|
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,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|