Flutter如何实现长按GestureDetector后滑动麦克风图标取消录音的UI效果
实现方案
首先在你的State类中新增两个成员变量,用于标记取消状态和判定取消的滑动阈值:
// 标记是否触发取消录音 bool _isCancelRecording = false; // 取消阈值,滑动距离超过该值即判定为取消,可根据实际需求调整数值 final double _cancelOffsetThreshold = 70;
新增取消录音的处理方法,用于滑动取消时停止录音、删除临时文件、重置状态:
Future<void> cancelRecord() async { await _audioRecorder?.stop(); // 删除未上传的临时录音文件 if(_filePath != null) { final tempFile = File(_filePath!); if(tempFile.existsSync()) { tempFile.deleteSync(); } } setState(() { _isRecording = false; _isCancelRecording = false; _isRecorded = false; Fluttertoast.showToast(msg: '已取消录音'); }); }
替换原有的GestureDetector代码,新增滑动监听逻辑、修改抬手后的判定逻辑,同时同步调整UI状态反馈:
GestureDetector( onLongPress: () async { // 每次长按开始前重置取消标记 _isCancelRecording = false; await pressStart(); }, // 监听长按过程中的滑动事件 onLongPressMoveUpdate: (details) { // 此处判断任意方向滑动超过阈值即触发取消,如需仅上滑取消可改为 details.offsetFromOrigin.dy < -_cancelOffsetThreshold if (details.offsetFromOrigin.distance.abs() > _cancelOffsetThreshold) { if(!_isCancelRecording) { setState(() { _isCancelRecording = true; }); Fluttertoast.showToast(msg: '松开即可取消录音'); } } else { if(_isCancelRecording) { setState(() { _isCancelRecording = false; }); Fluttertoast.showToast(msg: '松开完成录音'); } } }, onLongPressUp: () async { // 若已触发取消标记则走取消逻辑,不走原有上传流程 if(_isCancelRecording) { await cancelRecord(); return; } // 原有正常结束录音的逻辑保持不变 await pressUp(); Future.delayed(const Duration(milliseconds: 100), () { setState(() { _onFileUploadButtonPressed(); _onRecordAgainButtonPressed(); }); }); }, child: _isRecording != true ? Container( height: 55, width: 53, child: const Center( child: Icon( Icons.mic, size: 30, color: Colors.white, ), ), decoration: BoxDecoration( boxShadow: const [ BoxShadow( offset: Offset(0, 10), blurRadius: 10, color: Colors.grey) ], color: _isCancelRecording ? Colors.grey : Colors.black, shape: BoxShape.circle), ) : Container( height: 90, width: 90, child: Center( child: Container( decoration: BoxDecoration( boxShadow: const [ BoxShadow( offset: Offset(0, 10), blurRadius: 100, color: Colors.grey) ], color: _isCancelRecording ? Colors.grey[300] : Colors.red[300], shape: BoxShape.circle), child: Icon( _isCancelRecording ? Icons.delete : Icons.pause_circle_filled, size: 60, color: _isCancelRecording ? Colors.grey : Colors.red, ), ), ), decoration: BoxDecoration( boxShadow: const [ BoxShadow( offset: Offset(0, 10), blurRadius: 10, color: Colors.grey) ], color: _isCancelRecording ? Colors.grey : Colors.red, shape: BoxShape.circle), ) ),
补充说明
- 可自行调整
_cancelOffsetThreshold的数值适配不同屏幕的操作手感 - 如需限定仅特定方向滑动触发取消,修改
onLongPressMoveUpdate中的偏移判定条件即可 - 代码中同步增加了滑动到取消区域的UI反馈,可根据设计需求自行调整样式
内容的提问来源于stack exchange,提问作者samet demirtop
相关产品推荐
相关产品推荐

