Updating the UI as soon as audio is played completely

26 Views Asked by At

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;
                // }
              });
        });
  }
}



0

There are 0 best solutions below