Compare commits
No commits in common. "aba8b44ab8fcf3bd97f584b1c5ecd60990a4ab5b" and "0af37c5b879c25c4f1700dd8cf3a7d14887cbea2" have entirely different histories.
aba8b44ab8
...
0af37c5b87
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import '../interfaces/speech_recognition_service.dart';
|
import '../interfaces/speech_recognition_service.dart';
|
||||||
import '../yx_asr_service.dart';
|
import '../yx_asr_service.dart';
|
||||||
import '../models/speech_recognition_result.dart';
|
import '../models/speech_recognition_result.dart';
|
||||||
|
|
@ -70,7 +69,6 @@ class _RecordingButtonState extends State<RecordingButton>
|
||||||
late SpeechRecognitionService _speechService;
|
late SpeechRecognitionService _speechService;
|
||||||
bool _isListening = false;
|
bool _isListening = false;
|
||||||
bool _isInitialized = false;
|
bool _isInitialized = false;
|
||||||
bool _isProcessing = false; // 防抖标志
|
|
||||||
late AnimationController _animationController;
|
late AnimationController _animationController;
|
||||||
late Animation<double> _scaleAnimation;
|
late Animation<double> _scaleAnimation;
|
||||||
|
|
||||||
|
|
@ -148,29 +146,13 @@ class _RecordingButtonState extends State<RecordingButton>
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _toggleRecording() async {
|
Future<void> _toggleRecording() async {
|
||||||
// 防抖检查:如果正在处理中或未初始化或被禁用,则直接返回
|
if (!_isInitialized || !widget.enabled) return;
|
||||||
if (_isProcessing || !_isInitialized || !widget.enabled) return;
|
|
||||||
|
|
||||||
// 设置处理中标志,防止重复点击
|
|
||||||
setState(() {
|
|
||||||
_isProcessing = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 触觉反馈
|
|
||||||
await HapticFeedback.lightImpact();
|
|
||||||
|
|
||||||
// 播放点击动画
|
|
||||||
_animationController.forward().then((_) {
|
|
||||||
_animationController.reverse();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (_isListening) {
|
if (_isListening) {
|
||||||
await _speechService.stopListening();
|
await _speechService.stopListening();
|
||||||
} else {
|
} else {
|
||||||
await _speechService.startListening(
|
await _speechService.startListening(partialResults: widget.partialResults);
|
||||||
partialResults: widget.partialResults,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
widget.onError?.call(SpeechRecognitionError(
|
widget.onError?.call(SpeechRecognitionError(
|
||||||
|
|
@ -178,75 +160,52 @@ class _RecordingButtonState extends State<RecordingButton>
|
||||||
errorMsg: '切换录音状态失败: $e',
|
errorMsg: '切换录音状态失败: $e',
|
||||||
errorCode: null,
|
errorCode: null,
|
||||||
));
|
));
|
||||||
} finally {
|
|
||||||
// 延迟重置处理标志,确保有足够的防抖时间
|
|
||||||
Future.delayed(const Duration(milliseconds: 300), () {
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
_isProcessing = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Color iconColor;
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
|
Color buttonColor;
|
||||||
if (!widget.enabled || !_isInitialized) {
|
if (!widget.enabled || !_isInitialized) {
|
||||||
iconColor = widget.disabledColor ?? Colors.grey[850]!;
|
buttonColor = widget.disabledColor ?? Colors.grey;
|
||||||
|
} else if (_isListening) {
|
||||||
|
buttonColor = widget.recordingColor ?? Colors.red;
|
||||||
} else {
|
} else {
|
||||||
iconColor = _isListening
|
buttonColor = widget.idleColor ?? theme.primaryColor;
|
||||||
? (widget.recordingColor ?? const Color(0xFFFF5252))
|
|
||||||
: (widget.idleColor ?? const Color(0xFF2196F3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget button = AnimatedBuilder(
|
Widget button = AnimatedBuilder(
|
||||||
animation: _scaleAnimation,
|
animation: _scaleAnimation,
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Container(
|
return Transform.scale(
|
||||||
|
scale: _scaleAnimation.value,
|
||||||
|
child: Container(
|
||||||
width: widget.size,
|
width: widget.size,
|
||||||
height: widget.size,
|
height: widget.size,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: iconColor.withValues(alpha: 0.12),
|
color: buttonColor,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: buttonColor.withValues(alpha: 0.3),
|
||||||
|
blurRadius: _isListening ? 20 : 8,
|
||||||
|
spreadRadius: _isListening ? 5 : 2,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
borderRadius: BorderRadius.circular(widget.size / 2),
|
borderRadius: BorderRadius.circular(widget.size / 2),
|
||||||
onTap: _toggleRecording,
|
onTap: _toggleRecording,
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
top: 0,
|
|
||||||
child: Icon(
|
child: Icon(
|
||||||
_isListening ? Icons.stop_rounded : Icons.mic_rounded,
|
_isListening ? Icons.stop : Icons.mic,
|
||||||
size: widget.size * 0.55,
|
size: widget.size * 0.4,
|
||||||
color: iconColor,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_isProcessing || _isListening)
|
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
top: 0,
|
|
||||||
child: SizedBox(
|
|
||||||
width: widget.size,
|
|
||||||
height: widget.size,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
valueColor:
|
|
||||||
AlwaysStoppedAnimation<Color>(Colors.white),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue