Files
flutterApp/lib/features/remote_control/presentation/widgets/left_joystick_area.dart

139 lines
4.2 KiB
Dart

import 'dart:async';
import 'package:cc_ui_kit/cc_ui_kit.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:vibration/vibration.dart';
import 'package:maibu_satabot_v2/core/localization/app_localizations.dart';
import '../bloc/remote_control_cubit.dart';
class LeftJoystickArea extends StatefulWidget {
final bool isLocked;
final double width;
const LeftJoystickArea({
Key? key,
required this.isLocked,
required this.width,
}) : super(key: key);
@override
State<LeftJoystickArea> createState() => _LeftJoystickAreaState();
}
class _LeftJoystickAreaState extends State<LeftJoystickArea> {
int _lastSentY = 0;
bool _isTouching = false;
bool _hasShownNoPushDialog = false; // 防止重复弹窗
/// 检查是否可以控制,不能则弹出提示
bool _checkCanControl(BuildContext context) {
final cubit = context.read<RemoteControlCubit>();
if (!cubit.isStatusPushActive()) {
if (!_hasShownNoPushDialog) {
_hasShownNoPushDialog = true;
_showNoStatusPushDialog(context);
}
return false;
}
_hasShownNoPushDialog = false;
return true;
}
/// 显示暂未收到推送的提示弹窗(小圆角)
void _showNoStatusPushDialog(BuildContext context) {
showDialog(
context: context,
builder: (ctx) => Dialog(
backgroundColor: Colors.transparent,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
decoration: BoxDecoration(
color: const Color(0xE5333333),
borderRadius: BorderRadius.circular(12),
),
child: Text(
'暂未收到该机器的推送,不能控制',
style: const TextStyle(
color: Colors.white,
fontSize: 14,
),
),
),
),
);
// 1.5秒后自动关闭
Future.delayed(const Duration(milliseconds: 1500), () {
Navigator.of(context).pop();
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
IgnorePointer(
ignoring: widget.isLocked,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 300),
opacity: widget.isLocked ? 0.3 : 1.0,
child: CCJoystick(
radius: widget.width,
axisHint: AxisHint.forwardBackward,
onValueChanged: (value) {
if (!_checkCanControl(context)) return;
// 标记:正在触摸
_isTouching = true;
int currentY = value.y.toInt();
if (currentY != _lastSentY) {
_lastSentY = currentY;
debugPrint('左摇杆的数据- x: 0, y: $currentY');
context.read<RemoteControlCubit>().updateOriginY(currentY);
}
},
onPress: () {
if (!_checkCanControl(context)) return;
_isTouching = true;
debugPrint('onPress');
_triggerVibration();
},
onPanEnd: () async {
_hasShownNoPushDialog = false; // 松手重置,下次触摸重新检查
// 🔥 松手 100% 归零
debugPrint('onPanEnd');
await _stopJoystick();
},
),
),
),
const SizedBox(height: 18),
Text(
AppLocalizations.of(context).translate('remote_control.forward_backward'),
style: TextStyle(
color: Colors.white.withOpacity(0.5),
fontSize: 12,
fontWeight: FontWeight.w500,
),
),
],
);
}
// 统一停车方法(万能保险)
Future<void> _stopJoystick() async {
_isTouching = false;
_lastSentY = 0;
debugPrint('✅ 摇杆已停止 -> 强制 X=0, Y=0 停车');
// 🔥 使用安全方法,一次性清零双轴,确保只发送 (X=0, Y=0)
await context.read<RemoteControlCubit>().stopAllMovement();
}
void _triggerVibration() {
Vibration.hasVibrator().then((has) {
if (has ?? false) Vibration.vibrate(duration: 12);
});
}
}