Update RecordingButton design to match UI mockup

Design improvements based on provided mockup:

1. Color Updates:
   - Idle state: Blue (#2196F3) - matches mockup's blue recording button
   - Recording state: Red (#FF5252) - matches mockup's red stop button
   - Disabled state: Light grey (#9E9E9E) for better visibility
   - Processing state: Semi-transparent versions of respective colors

2. Shape Changes:
   - Idle state: Circle (for recording button)
   - Recording state: Rounded rectangle (12px radius) for stop button
   - Smooth transitions between shapes using BoxShape

3. Icon Improvements:
   - Use rounded icons (mic_rounded, stop_rounded) for modern look
   - Adjust icon sizes: recording (40% of button), stop (35% of button)
   - Better proportions matching the design intent

4. Shadow Enhancements:
   - Increased blur radius for idle state (8→12px) for better depth
   - Dynamic shadow based on button state
   - Enhanced spread radius for better visual impact

5. Interactive Elements:
   - InkWell borderRadius adapts to button shape
   - Smooth transitions between circular and rectangular ripple effects

These changes create a modern, professional appearance that matches
common design patterns and provides clear visual feedback for different states.
This commit is contained in:
Max 2025-09-09 14:20:10 +08:00
parent 6146508bed
commit 3e8fe73e27
1 changed files with 19 additions and 14 deletions

View File

@ -159,7 +159,7 @@ class _RecordingButtonState extends State<RecordingButton>
try {
//
await HapticFeedback.lightImpact();
//
_animationController.forward().then((_) {
_animationController.reverse();
@ -168,7 +168,8 @@ class _RecordingButtonState extends State<RecordingButton>
if (_isListening) {
await _speechService.stopListening();
} else {
await _speechService.startListening(partialResults: widget.partialResults);
await _speechService.startListening(
partialResults: widget.partialResults);
}
} catch (e) {
widget.onError?.call(SpeechRecognitionError(
@ -190,17 +191,19 @@ class _RecordingButtonState extends State<RecordingButton>
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
Color buttonColor;
if (!widget.enabled || !_isInitialized) {
buttonColor = widget.disabledColor ?? Colors.grey;
buttonColor = widget.disabledColor ?? Colors.grey[400]!;
} else if (_isProcessing) {
buttonColor = (widget.idleColor ?? theme.primaryColor).withValues(alpha: 0.7);
buttonColor = _isListening
? (widget.recordingColor ?? const Color(0xFFFF5252))
.withValues(alpha: 0.7)
: (widget.idleColor ?? const Color(0xFF2196F3))
.withValues(alpha: 0.7);
} else if (_isListening) {
buttonColor = widget.recordingColor ?? Colors.red;
buttonColor = widget.recordingColor ?? const Color(0xFFFF5252); //
} else {
buttonColor = widget.idleColor ?? theme.primaryColor;
buttonColor = widget.idleColor ?? const Color(0xFF2196F3); //
}
Widget button = AnimatedBuilder(
@ -213,12 +216,13 @@ class _RecordingButtonState extends State<RecordingButton>
height: widget.size,
decoration: BoxDecoration(
color: buttonColor,
shape: BoxShape.circle,
shape: _isListening ? BoxShape.rectangle : BoxShape.circle,
borderRadius: _isListening ? BorderRadius.circular(12) : null,
boxShadow: [
BoxShadow(
color: buttonColor.withValues(alpha: 0.3),
blurRadius: _isListening ? 20 : 8,
spreadRadius: _isListening ? 5 : 2,
blurRadius: _isListening ? 20 : 12,
spreadRadius: _isListening ? 5 : 3,
),
],
),
@ -233,12 +237,13 @@ class _RecordingButtonState extends State<RecordingButton>
height: widget.size * 0.4,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
valueColor:
AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: Icon(
_isListening ? Icons.stop : Icons.mic,
size: widget.size * 0.4,
_isListening ? Icons.stop_rounded : Icons.mic_rounded,
size: widget.size * (_isListening ? 0.35 : 0.4),
color: Colors.white,
),
),