|
|
@@ -0,0 +1,158 @@ |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:flutter_sound/flutter_sound.dart'; |
|
|
|
import 'package:audioplayers/audioplayers.dart'; |
|
|
|
import 'package:permission_handler/permission_handler.dart'; |
|
|
|
|
|
|
|
class SoundRecordScene extends StatefulWidget { |
|
|
|
@override |
|
|
|
_SoundRecordSceneState createState() => _SoundRecordSceneState(); |
|
|
|
} |
|
|
|
|
|
|
|
class _SoundRecordSceneState extends State<SoundRecordScene> { |
|
|
|
FlutterSoundRecorder? _soundRecorder; |
|
|
|
AudioPlayer? _audioPlayer; |
|
|
|
String? _audioFilePath; |
|
|
|
ScrollController _scrollController = ScrollController(); |
|
|
|
List<String> _logs = []; |
|
|
|
|
|
|
|
@override |
|
|
|
void initState() { |
|
|
|
super.initState(); |
|
|
|
_soundRecorder = FlutterSoundRecorder(); |
|
|
|
_audioPlayer = AudioPlayer(); |
|
|
|
_requestPermissions(); |
|
|
|
} |
|
|
|
|
|
|
|
// 请求麦克风权限 |
|
|
|
void _requestPermissions() async { |
|
|
|
try { |
|
|
|
await Permission.microphone.request(); |
|
|
|
} catch (e) { |
|
|
|
_log('播放录音失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 开始录音 |
|
|
|
void _startRecording() async { |
|
|
|
try { |
|
|
|
_log('录音开始'); |
|
|
|
final tempPath = |
|
|
|
'/data/user/0/com.example.flutter_app/cache/recorded_audio.aac'; // 可根据需要调整路径 |
|
|
|
await _soundRecorder?.startRecorder( |
|
|
|
toFile: tempPath, |
|
|
|
codec: Codec.aacADTS, |
|
|
|
); |
|
|
|
setState(() { |
|
|
|
_audioFilePath = tempPath; |
|
|
|
}); |
|
|
|
} catch (e) { |
|
|
|
_log('播放录音失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 停止录音 |
|
|
|
void _stopRecording() async { |
|
|
|
try { |
|
|
|
await _soundRecorder?.stopRecorder(); |
|
|
|
_log('录音停止'); |
|
|
|
} catch (e) { |
|
|
|
_log('播放录音失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 播放录音 |
|
|
|
void _playRecording() async { |
|
|
|
if (_audioFilePath != null) { |
|
|
|
await _audioPlayer?.play(DeviceFileSource(_audioFilePath!)); |
|
|
|
_log('播放录音'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 添加日志信息并自动滚动 |
|
|
|
void _log(String message) { |
|
|
|
setState(() { |
|
|
|
_logs.add(message); // 从顶部插入新日志 |
|
|
|
}); |
|
|
|
_scrollToBottom(); |
|
|
|
} |
|
|
|
|
|
|
|
// 滚动到底部 |
|
|
|
void _scrollToBottom() { |
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) { |
|
|
|
if (_scrollController.hasClients) { |
|
|
|
_scrollController.animateTo( |
|
|
|
_scrollController.position.maxScrollExtent, // 滚动到底部 |
|
|
|
duration: Duration(milliseconds: 200), |
|
|
|
curve: Curves.easeInOut, |
|
|
|
); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
void dispose() { |
|
|
|
_soundRecorder?.closeRecorder(); |
|
|
|
_audioPlayer?.dispose(); |
|
|
|
_scrollController.dispose(); |
|
|
|
super.dispose(); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
return Scaffold( |
|
|
|
appBar: AppBar(title: Text('录音与播放')), |
|
|
|
body: Column( |
|
|
|
children: [ |
|
|
|
// 滑动面板(日志区域) |
|
|
|
Expanded( |
|
|
|
child: Padding( |
|
|
|
padding: const EdgeInsets.all(8.0), |
|
|
|
child: Container( |
|
|
|
decoration: BoxDecoration( |
|
|
|
border: Border.all(color: Colors.blue), |
|
|
|
borderRadius: BorderRadius.circular(10), |
|
|
|
), |
|
|
|
child: ListView.builder( |
|
|
|
controller: _scrollController, |
|
|
|
itemCount: _logs.length, |
|
|
|
itemBuilder: (context, index) { |
|
|
|
return Padding( |
|
|
|
padding: const EdgeInsets.symmetric( |
|
|
|
vertical: 0.0), // 设置日志项间的垂直间距 |
|
|
|
child: ListTile( |
|
|
|
title: Text(_logs[index]), |
|
|
|
), |
|
|
|
); |
|
|
|
}, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
// 按钮区域 |
|
|
|
GestureDetector( |
|
|
|
onTapDown: (details) { |
|
|
|
_startRecording(); // 按下时开始录音 |
|
|
|
}, |
|
|
|
onTapUp: (details) { |
|
|
|
_stopRecording(); // 抬起时停止录音并播放 |
|
|
|
_playRecording(); // 播放录音 |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
margin: EdgeInsets.all(20), |
|
|
|
padding: EdgeInsets.all(20), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.blue, |
|
|
|
shape: BoxShape.circle, |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.mic, |
|
|
|
color: Colors.white, |
|
|
|
size: 50, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} |