import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:trackoffical_app/generated/assets.dart'; import 'package:trackoffical_app/service/app.dart'; import 'package:rive/rive.dart'; import 'package:vibration/vibration.dart'; class ButtonPunch extends StatefulWidget { const ButtonPunch({ super.key, required this.onPressed, required this.isWarn, }); final VoidCallback? onPressed; final bool isWarn; @override State createState() { return ButtonPunchState(); } } class ButtonPunchState extends State with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation _animation; var _isActive = true; @override void initState() { super.initState(); _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 500), reverseDuration: const Duration(milliseconds: 500), )..repeat(reverse: true); _animation = ColorTween(begin: Colors.white, end: Colors.red) .animate(_animationController) ..addListener(() { setState(() { // The state that has changed here is the animation object’s value. }); }); loopVibration(); } Future loopVibration() async{ while(_isActive){ await Future.delayed(500.milliseconds); if(widget.isWarn){ await App.to.vibrate(duration: 100, repeat: 1); } } } @override void didUpdateWidget(covariant ButtonPunch oldWidget) { super.didUpdateWidget(oldWidget); final oldEnabled = oldWidget.onPressed != null; final newEnabled = widget.onPressed != null; if (oldEnabled != newEnabled) { if (newEnabled) { _animationController.repeat(reverse: true); } else { _animationController.stop(); } } } @override void dispose() { _animationController.dispose(); _isActive=false; super.dispose(); } @override Widget build(BuildContext context) { final image = widget.onPressed != null? 'assets/images/btn_punch.png': 'assets/images/btn_punch_disable.png'; final boxShadow = []; final children = []; if(widget.isWarn){ boxShadow.add(BoxShadow( color: Colors.red.withAlpha(150), offset: const Offset(0.0, 0.0), //阴影y轴偏移量 blurRadius: 6, //阴影模糊程度 spreadRadius: widget.onPressed!= null? 2: 1 //阴影扩散程度 )); children.add(const RiveAnimation.asset(Assets.imagesAmPunchButtonFlash, fit: BoxFit.fill)); }else{ boxShadow.add(BoxShadow( color: Colors.grey.withAlpha(150), offset: const Offset(2.0, 2.0), //阴影y轴偏移量 blurRadius: 6, //阴影模糊程度 spreadRadius: widget.onPressed!= null? 5: 1 //阴影扩散程度 )); } children.add(GestureDetector( onTap: widget.onPressed, child: Container( width: 56, height: 56, decoration: BoxDecoration( color: Colors.white, image: DecorationImage( image: AssetImage(image)), borderRadius: BorderRadius.circular(28), boxShadow: boxShadow, ), ), )); return SizedBox(height: 90, width: 90, child: Stack( alignment: Alignment.center, children: children, )); } } void main() async { runApp(Container( color: Colors.white, child: Column( children: [ const Spacer(), ButtonPunch( onPressed: () { }, isWarn: false, ) ], ) ) ) ; }