MIF_E31230910_MP-HRIS-MOBILE/lib/widgets/atoms/bouncy_tap.dart

87 lines
2.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:haptic_feedback/haptic_feedback.dart';
class BouncyTap extends StatefulWidget {
final Widget child;
final VoidCallback? onPressed;
final double scaleDown;
final Duration duration;
final bool enableHaptic;
final HitTestBehavior behavior;
const BouncyTap({
super.key,
required this.child,
this.onPressed,
this.scaleDown = 0.95,
this.duration = const Duration(milliseconds: 100),
this.enableHaptic = true,
this.behavior = HitTestBehavior.opaque,
});
@override
State<BouncyTap> createState() => _BouncyTapState();
}
class _BouncyTapState extends State<BouncyTap> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _scaleAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: widget.duration);
_scaleAnimation = Tween<double>(begin: 1.0, end: widget.scaleDown).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _onTapDown(TapDownDetails details) {
if (widget.onPressed != null) {
if (widget.enableHaptic) {
Haptics.vibrate(HapticsType.light);
}
_controller.forward();
}
}
void _onTapUp(TapUpDetails details) {
if (widget.onPressed != null) {
_controller.reverse();
widget.onPressed!();
}
}
void _onTapCancel() {
if (widget.onPressed != null) {
_controller.reverse();
}
}
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: widget.behavior,
onTapDown: _onTapDown,
onTapUp: _onTapUp,
onTapCancel: _onTapCancel,
child: AnimatedBuilder(
animation: _scaleAnimation,
builder: (context, child) {
return Transform.scale(
scale: _scaleAnimation.value,
alignment: Alignment.center,
child: widget.child,
);
},
),
);
}
}