import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'wave_painter.dart'; class FluidSphereButton extends StatefulWidget { final double percentage; final Color waterColor; final VoidCallback onLongPressStart; final VoidCallback onLongPressEnd; const FluidSphereButton({ super.key, required this.percentage, required this.waterColor, required this.onLongPressStart, required this.onLongPressEnd, }); @override State createState() => _FluidSphereButtonState(); } class _FluidSphereButtonState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(seconds: 4), )..repeat(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return GestureDetector( onLongPress: widget.onLongPressStart, onLongPressUp: widget.onLongPressEnd, child: AnimatedContainer( duration: const Duration(seconds: 1), width: 260, height: 260, decoration: BoxDecoration( shape: BoxShape.circle, boxShadow: [ BoxShadow( color: widget.waterColor.withOpacity(0.3), blurRadius: 40, offset: const Offset(0, 20), ), BoxShadow( color: Colors.white.withOpacity(0.9), blurRadius: 20, offset: const Offset(-10, -10), ), ], ), child: ClipOval( child: Stack( children: [ Container(color: Colors.white.withOpacity(0.2)), AnimatedBuilder( animation: _controller, builder: (context, child) { return CustomPaint( painter: WavePainter( animationValue: _controller.value, percentage: widget.percentage, color: widget.waterColor, ), size: Size.infinite, ); }, ), Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.white.withOpacity(0.6), Colors.transparent, Colors.transparent, Colors.white.withOpacity(0.1), ], stops: const [0.0, 0.4, 0.7, 1.0], ), ), ), Positioned( top: 30, right: 30, child: Container( width: 40, height: 20, decoration: BoxDecoration( color: Colors.white.withOpacity(0.4), borderRadius: const BorderRadius.all(Radius.elliptical(40, 20)), ), ), ), Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( "HOLD TO INFUSE", style: GoogleFonts.montserrat( color: widget.percentage > 0.6 ? Colors.white : Colors.black45, fontSize: 10, letterSpacing: 2.0, fontWeight: FontWeight.w700, ), ), ], ), ), ], ), ), ), ); } }