feat(ui): Show an indicator for the swipe gesture
This commit is contained in:
parent
adcfdc1a73
commit
e5553699c5
@ -1,13 +1,27 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BlinkingMicrophoneIcon extends StatefulWidget {
|
||||
const BlinkingMicrophoneIcon({ super.key });
|
||||
class BlinkingIcon extends StatefulWidget {
|
||||
const BlinkingIcon({
|
||||
required this.icon,
|
||||
required this.duration,
|
||||
required this.start,
|
||||
required this.end,
|
||||
this.size,
|
||||
this.delay = Duration.zero,
|
||||
super.key,
|
||||
});
|
||||
final IconData icon;
|
||||
final double? size;
|
||||
final Duration delay;
|
||||
final Duration duration;
|
||||
final Color start;
|
||||
final Color end;
|
||||
|
||||
@override
|
||||
BlinkingMicrophoneIconState createState() => BlinkingMicrophoneIconState();
|
||||
BlinkingIconState createState() => BlinkingIconState();
|
||||
}
|
||||
|
||||
class BlinkingMicrophoneIconState extends State<BlinkingMicrophoneIcon> with TickerProviderStateMixin {
|
||||
class BlinkingIconState extends State<BlinkingIcon> with TickerProviderStateMixin {
|
||||
late final AnimationController _recordingBlinkController;
|
||||
late final Animation<Color?> _recordingBlink;
|
||||
bool _blinkForward = true;
|
||||
@ -17,13 +31,13 @@ class BlinkingMicrophoneIconState extends State<BlinkingMicrophoneIcon> with Tic
|
||||
super.initState();
|
||||
|
||||
_recordingBlinkController = AnimationController(
|
||||
duration: const Duration(milliseconds: 600),
|
||||
duration: widget.duration,
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_recordingBlink = ColorTween(
|
||||
begin: Colors.white,
|
||||
end: Colors.red.shade600,
|
||||
begin: widget.start,
|
||||
end: widget.end,
|
||||
).animate(_recordingBlinkController)
|
||||
..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed ||
|
||||
@ -38,9 +52,14 @@ class BlinkingMicrophoneIconState extends State<BlinkingMicrophoneIcon> with Tic
|
||||
}
|
||||
});
|
||||
|
||||
_recordingBlinkController.forward();
|
||||
_startBlinking();
|
||||
}
|
||||
|
||||
Future<void> _startBlinking() async {
|
||||
await Future<void>.delayed(widget.delay);
|
||||
await _recordingBlinkController.forward();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_recordingBlinkController.dispose();
|
||||
@ -53,8 +72,9 @@ class BlinkingMicrophoneIconState extends State<BlinkingMicrophoneIcon> with Tic
|
||||
animation: _recordingBlink,
|
||||
builder: (_, __) {
|
||||
return Icon(
|
||||
Icons.mic,
|
||||
widget.icon,
|
||||
color: _recordingBlink.value,
|
||||
size: widget.size,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -290,7 +290,12 @@ class ConversationBottomRowState extends State<ConversationBottomRow> {
|
||||
onPressed: null,
|
||||
heroTag: 'fabDragged',
|
||||
backgroundColor: Colors.red.shade600,
|
||||
child: const BlinkingMicrophoneIcon(),
|
||||
child: BlinkingIcon(
|
||||
icon: Icons.mic,
|
||||
duration: const Duration(milliseconds: 600),
|
||||
start: Colors.white,
|
||||
end: Colors.red.shade600,
|
||||
),
|
||||
),
|
||||
),
|
||||
childWhenDragging: SizedBox(
|
||||
|
@ -461,6 +461,52 @@ class ConversationPageState extends State<ConversationPage> with TickerProviderS
|
||||
),
|
||||
),
|
||||
|
||||
// Indicator for the swipe to lock gesture
|
||||
Positioned(
|
||||
right: 8,
|
||||
bottom: 100,
|
||||
child: IgnorePointer(
|
||||
child: BlocBuilder<ConversationBloc, ConversationState>(
|
||||
builder: (context, state) {
|
||||
return AnimatedScale(
|
||||
scale: state.isRecording && !state.isLocked ? 1 : 0,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: SizedBox(
|
||||
height: 24 * 3,
|
||||
width: 47,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: const [
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
child: Icon(
|
||||
Icons.keyboard_arrow_up,
|
||||
size: 48,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 12,
|
||||
child: Icon(
|
||||
Icons.keyboard_arrow_up,
|
||||
size: 48,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 24,
|
||||
child: Icon(
|
||||
Icons.keyboard_arrow_up,
|
||||
size: 48,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Positioned(
|
||||
right: 8,
|
||||
bottom: 250,
|
||||
@ -493,7 +539,12 @@ class ConversationPageState extends State<ConversationPage> with TickerProviderS
|
||||
Colors.red.shade600 :
|
||||
Colors.grey,
|
||||
child: state.isLocked ?
|
||||
const BlinkingMicrophoneIcon() :
|
||||
BlinkingIcon(
|
||||
icon: Icons.mic,
|
||||
duration: const Duration(milliseconds: 600),
|
||||
start: Colors.white,
|
||||
end: Colors.red.shade600,
|
||||
) :
|
||||
const Icon(Icons.lock, color: Colors.white),
|
||||
),
|
||||
),
|
||||
|
Loading…
Reference in New Issue
Block a user