import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; import '../bloc/remote_control_cubit.dart'; class EmergencyStopButton extends StatefulWidget { final double width; const EmergencyStopButton({ Key? key, this.width = 120, }) : super(key: key); @override State createState() => _EmergencyStopButtonState(); } class _EmergencyStopButtonState extends State with TickerProviderStateMixin { late AnimationController _progressController; bool _isPressing = false; @override void initState() { super.initState(); _progressController = AnimationController( vsync: this, duration: const Duration(seconds: 3), ); } @override void dispose() { _progressController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { // 监听 Cubit 中的急停状态 final isEmergencyActive = context .watch() .state .isEmergency; final width = widget.width * 0.65; final double indicatorSize = width + 10; return GestureDetector( // 1. 处理点击:仅在未急停时触发 onTap: () { if (!isEmergencyActive) { context.read().updateEmergency(true); HapticFeedback.heavyImpact(); // 震动反馈 } }, // 2. 处理长按开始:仅在已急停时触发解除逻辑 onLongPressStart: (_) { if (isEmergencyActive) { setState(() => _isPressing = true); _progressController.forward(from: 0).then((_) { if (_isPressing) { // 进度走完且仍在按压 context.read().updateEmergency(false); HapticFeedback.vibrate(); setState(() => _isPressing = false); } }); } }, // 3. 处理松手:重置进度 onLongPressEnd: (_) { _isPressing = false; _progressController.stop(); _progressController.value = 0; setState(() {}); }, child: Stack( alignment: Alignment.center, children: [ // 对应 Compose 的 Canvas 绘制进度环 if (_isPressing) SizedBox( width: indicatorSize, height: indicatorSize, child: CircularProgressIndicator( value: _progressController.value, strokeWidth: 10, color: Colors.red.withOpacity(0.8), backgroundColor: Colors.red.withValues(alpha: 0.2), ), ), Container( width: width, height: width, decoration: BoxDecoration( shape: BoxShape.circle, // 根据状态切换颜色,对应 Color(0x80C53030) color: isEmergencyActive ? Colors.red.withOpacity(0.5) : const Color(0x80C53030), boxShadow: isEmergencyActive ? [ BoxShadow( color: Colors.red.withValues(alpha: 0.5), blurRadius: 20, ), ] : [], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SvgPicture.asset('assets/svgs/remote_alert.svg',width: width * 0.4,color: Colors.white.withValues(alpha: 0.5),), const SizedBox(height: 6), Text( isEmergencyActive ? "急停中" : "急停", style: TextStyle( color: Colors.white.withValues(alpha: 0.5), fontSize: 14, fontWeight: FontWeight.w900, ), ), ], ), ), ], ), ); } }