Compare commits

..

No commits in common. "aba8b44ab8fcf3bd97f584b1c5ecd60990a4ab5b" and "0af37c5b879c25c4f1700dd8cf3a7d14887cbea2" have entirely different histories.

1 changed files with 35 additions and 76 deletions

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../interfaces/speech_recognition_service.dart';
import '../yx_asr_service.dart';
import '../models/speech_recognition_result.dart';
@ -70,7 +69,6 @@ class _RecordingButtonState extends State<RecordingButton>
late SpeechRecognitionService _speechService;
bool _isListening = false;
bool _isInitialized = false;
bool _isProcessing = false; //
late AnimationController _animationController;
late Animation<double> _scaleAnimation;
@ -148,29 +146,13 @@ class _RecordingButtonState extends State<RecordingButton>
}
Future<void> _toggleRecording() async {
//
if (_isProcessing || !_isInitialized || !widget.enabled) return;
//
setState(() {
_isProcessing = true;
});
if (!_isInitialized || !widget.enabled) return;
try {
//
await HapticFeedback.lightImpact();
//
_animationController.forward().then((_) {
_animationController.reverse();
});
if (_isListening) {
await _speechService.stopListening();
} else {
await _speechService.startListening(
partialResults: widget.partialResults,
);
await _speechService.startListening(partialResults: widget.partialResults);
}
} catch (e) {
widget.onError?.call(SpeechRecognitionError(
@ -178,74 +160,51 @@ class _RecordingButtonState extends State<RecordingButton>
errorMsg: '切换录音状态失败: $e',
errorCode: null,
));
} finally {
//
Future.delayed(const Duration(milliseconds: 300), () {
if (mounted) {
setState(() {
_isProcessing = false;
});
}
});
}
}
@override
Widget build(BuildContext context) {
Color iconColor;
final theme = Theme.of(context);
Color buttonColor;
if (!widget.enabled || !_isInitialized) {
iconColor = widget.disabledColor ?? Colors.grey[850]!;
buttonColor = widget.disabledColor ?? Colors.grey;
} else if (_isListening) {
buttonColor = widget.recordingColor ?? Colors.red;
} else {
iconColor = _isListening
? (widget.recordingColor ?? const Color(0xFFFF5252))
: (widget.idleColor ?? const Color(0xFF2196F3));
buttonColor = widget.idleColor ?? theme.primaryColor;
}
Widget button = AnimatedBuilder(
animation: _scaleAnimation,
builder: (context, child) {
return Container(
width: widget.size,
height: widget.size,
decoration: BoxDecoration(
color: iconColor.withValues(alpha: 0.12),
shape: BoxShape.circle,
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(widget.size / 2),
onTap: _toggleRecording,
child: Stack(
children: [
Positioned(
left: 0,
right: 0,
bottom: 0,
top: 0,
child: Icon(
_isListening ? Icons.stop_rounded : Icons.mic_rounded,
size: widget.size * 0.55,
color: iconColor,
),
),
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),
),
),
)
],
return Transform.scale(
scale: _scaleAnimation.value,
child: Container(
width: widget.size,
height: widget.size,
decoration: BoxDecoration(
color: buttonColor,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: buttonColor.withValues(alpha: 0.3),
blurRadius: _isListening ? 20 : 8,
spreadRadius: _isListening ? 5 : 2,
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(widget.size / 2),
onTap: _toggleRecording,
child: Icon(
_isListening ? Icons.stop : Icons.mic,
size: widget.size * 0.4,
color: Colors.white,
),
),
),
),