in my app i can successfully toggle between the play and pause button of my audio player but when the player is in play mode (i.e. the option of pausing is being shown) and the audio gets completed i want the button to automatically switch back to the original state i.e. the button become 'start playing' and i can start from the beginning. Ive tried soooo many methods and at last im at this code with proper toggling b/w play and pause the only problem is the pause button not toggling back to the play button when the audio playback is finished
here's my code for reference ive tried this and just want to know the last part i.e my main question:
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_sound/flutter_sound.dart' as fsound;
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
class NewJournalPage extends StatefulWidget {
const NewJournalPage({super.key});
@override
State<NewJournalPage> createState() => _NewJournalPageState();
}
class _NewJournalPageState extends State<NewJournalPage> {
List<Widget> journalContent = [];
bool tick = true;
fsound.FlutterSoundRecorder recorder = fsound.FlutterSoundRecorder();
fsound.FlutterSoundPlayer player = fsound.FlutterSoundPlayer();
List<String> filePath = [];
bool micOn = false;
bool isPlaying = false;
bool isCompleted = false;
ValueNotifier<bool> isPlayingNotifier = ValueNotifier<bool>(false);
@override
void initState() {
// TODO: implement initState
super.initState();
init();
}
Future<String?> startRecording() async {
final directory = await getApplicationDocumentsDirectory();
final currentFilePath =
'${directory.path}/recording_${DateTime.now().millisecondsSinceEpoch}.aac';
await recorder.openRecorder();
await recorder.startRecorder(
toFile: currentFilePath, codec: fsound.Codec.aacMP4);
setState(() {
micOn = true;
filePath.insert(0, currentFilePath);
});
return filePath[0];
}
Future<void> stopRecording() async {
await recorder.stopRecorder();
setState(() {
micOn = false;
journalContent.insert(
0,
AudioItem(
filePath: filePath[0],
playFunction: startPlaying,
stopFunction: pausePlaying,
isplayingNotifier: isPlayingNotifier,
),
// VoiceNotePlayer(audioLocation: filePath[0]),
);
});
}
Future<void> startPlaying() async {
if (!isPlayingNotifier.value) {
await player.openPlayer();
await player.startPlayer(fromURI: filePath[0]);
isPlayingNotifier.value = true;
} else {
await player.resumePlayer();
isPlayingNotifier.value = true;
player.onProgress!.listen(
(event) async {
if (event.duration == event.position) {
await player.stopPlayer();
isPlayingNotifier.value = false;
await player.closePlayer();
isCompleted = true;
}
},
);
}
}
Future<void> pausePlaying() async {
if(!isCompleted)
{await player.pausePlayer();
isPlayingNotifier.value = false;}
// setState(() {
// isPlaying = false;
// });
}
@override
void dispose() {
recorder.closeRecorder();
player.closePlayer();
isPlayingNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF4DCDFF),
Color(0XFF0080bf),
],
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
//----------------------
//appbar
//----------------------
appBar: CustomAppBar(tick: tick),
//----------------------
//bottom app bar
//----------------------
bottomNavigationBar: BottomAppBar(
height: 70,
color: Colors.white.withOpacity(0.13),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//---mic & stop button
micOn
? CustomIconButton(
size: 30,
onPressFunc: () => stopRecording(),
icon: Icons.stop_circle_outlined,
)
: CustomIconButton(
onPressFunc: () => startRecording(),
icon: Icons.mic_none,
size: 30,
),
//---camera button
CustomIconButton(
onPressFunc: () {},
icon: Icons.photo_camera_outlined,
size: 30,
),
],
),
),
//----------------------
//main body
//----------------------
body: Column(
children: [
const SizedBox(height: 20),
Flexible(
child: ListView.builder(
itemCount: journalContent.length,
itemBuilder: ((context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
journalContent[index],
],
);
}),
],
),
),
);
}
}
//
//
//all the custom widgets here
//
//
class AudioItem extends StatefulWidget {
final String filePath;
final VoidCallback playFunction;
final VoidCallback stopFunction;
final ValueNotifier<bool> isplayingNotifier;
const AudioItem({
required this.filePath,
required this.playFunction,
required this.stopFunction,
required this.isplayingNotifier,
Key? key,
}) : super(key: key);
@override
State<AudioItem> createState() => _AudioItemState();
}
class _AudioItemState extends State<AudioItem> {
bool playing = false;
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: widget.isplayingNotifier,
builder: (context, isPlaying, child) {
return ListTile(
leading: playing
? const Icon(
Icons.pause_circle_outline_rounded,
color: Colors.white,
size: 40,
)
: const Icon(
Icons.play_circle_outline_rounded,
color: Colors.white,
size: 40,
),
title: Text(
playing ? 'Stop Playing' : 'Start Playing',
style: const TextStyle(
color: Colors.white,
fontSize: 16,
),
),
onTap: () {
setState(() {
playing = !playing;
});
playing ? widget.playFunction() : widget.stopFunction();
// if (widget.isplayingNotifier.value == false) {
// playing = false;
// }
});
});
}
}