How to create a listTile from a class in Flutter based on an collected id from the previous page

21 views Asked by At

Please I am very new to flutter. I am working on a project and i got stuck in the implementation. I was wondering if you can help out. I am creating an audiobook. It converts pdf to audiofiles. I created a list of the books on a screen and if you tap on a book, it should list out the audios associated with it. Now the problem is that I split the audios into different parts as seen below:

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'audio.dart';


class Audios with ChangeNotifier {
  final List<Audio> _audios = [
    Audio(
        audioId: 1,
        bookId: 1,
        userId: 1,
        audioFile: [
          "https://myaudiobookapp.s3.eu-central-1.amazonaws.com/the_frog_prince_part1.mp3",
          "https://myaudiobookapp.s3.eu-central-1.amazonaws.com/the_frog_prince_part2.mp3",
          "https://myaudiobookapp.s3.eu-central-1.amazonaws.com/the_frog_prince_part3.mp3"
        ],
        audioName: "the_frog_prince",
        bookImage:
            "https://myaudiobookapp.s3.amazonaws.com/1_The-Frog-Prince-Landscape-Book-CKF-FKB.pdf.png"),
    Audio(
      audioId: 2,
      bookId: 2,
      userId: 1,
      audioFile: [
        "https://myaudiobookapp.s3.amazonaws.com/sara_menker_part1.mp3"
      ],
      audioName: "sara_menker",
      bookImage:
          "https://myaudiobookapp.s3.amazonaws.com/Data_Analysis_Plan_of_Sara_Menker.pdf.png",
    ),
  ];

  // current song playing index
  int? _currentAudioIndex;

/*

A U D I O P L A Y E R

*/

// audio player

  final AudioPlayer _audioPlayer = AudioPlayer();

// durations
  Duration _currentDuration = Duration.zero;
  Duration _totalDuration = Duration.zero;

// constructor
  Audios() {
    listenToDuration();
  }

// initially not playing
  bool _isPlaying = false;

// play the audio

  void playAudio(int index) async {
    // final audIndex = _audios.indexWhere((aud) => aud.audioId == index + 1);
    int i = 0;
    while (i < _audios[index].audioFile.length) {
      final audioUrl = _audios[index].audioFile[i];
      await _audioPlayer.stop();
      await _audioPlayer.play(audioUrl);
      _isPlaying = true;
      _currentAudioIndex = index;
      notifyListeners();
    }
  }

// pause current song
  void pauseAudio() async {
    await _audioPlayer.pause();
    _isPlaying = false;
    notifyListeners();
  }

// resume playing
  void resumeAudio() async {
    await _audioPlayer.resume();
    _isPlaying = true;
    notifyListeners();
  }

// pause or resume
  void pauseOrResumeAudio() async {
    if (_isPlaying) {
      pauseAudio();
    } else {
      resumeAudio();
    }
    notifyListeners();
  }

// seek to a specific position in the current audio
  void seek(Duration position) async {
    await _audioPlayer.seek(position);
  }

// play next song
  void playNextAudio() {
    if (_currentAudioIndex != null) {
      if (_currentAudioIndex! < _audios.length - 1) {
        // go to the next audio if it's not the last audio
        currentAudioIndex = _currentAudioIndex! + 1;
      } else {
        // if it's the last song, loop back to the first song
        currentAudioIndex = 0;
      }
    }
  }

// play previous song

  void playPreviousAudio() {
    // if more than 2 seconds have passed, restart the current audio
    if (_currentDuration.inSeconds > 2) {
      // if it's within first 2 second of the audio, go to previous song
      seek(Duration.zero);
    } else {
      if (_currentAudioIndex! > 0) {
        currentAudioIndex = _currentAudioIndex! - 1;
      } else {
        // if it's the first song, loop back to last song
        currentAudioIndex = _audios.length - 1;
      }
    }
  }

// listen to duration
  void listenToDuration() {
    // listen for total Duration
    _audioPlayer.onDurationChanged.listen((newDuration) {
      _totalDuration = newDuration;
      notifyListeners();
    });

    // listen for current Duration
    _audioPlayer.onAudioPositionChanged.listen((newPosition) {
      _currentDuration = newPosition;
      notifyListeners();
    });

    // listen for song completion
    _audioPlayer.onPlayerCompletion.listen((event) {});
  }

// dispose audio player

/*

G E T T E R S


*/

  // List<Audio> get items {
  //   return [...audios];
  // }
  List<Audio> get audios => _audios;
  int? get currentAudioIndex => _currentAudioIndex;
  bool get isPlaying => _isPlaying;
  Duration get currentDuration => _currentDuration;
  Duration get totalDuration => _totalDuration;

  List getAudioFilesById(int audioId) {
    final audio = _audios.firstWhere((audio) => audio.audioId == audioId,
        orElse: () => throw Exception('Audio ID not found'));
    return audio.audioFile;
  }

/*


S E T T E R S


*/

  set currentAudioIndex(int? newIndex) {
    //update current Audio Index
    _currentAudioIndex = newIndex;

    if (newIndex != null) {
      playAudio(newIndex);
    }

    //update UI
    notifyListeners();
  }

  Audio findById(int id) {
    return audios.firstWhere((audio) => audio.audioId == id);
  }

}

So now, I have to let it know the selected book and create a listTile of audioFiles related to that book. I also want the audioName to be reflected for each audioFile.

This is the audioList widget I created:

 import 'package:audio_book_app/screens/audio_page_screen.dart';
import 'package:flutter/material.dart';
import 'package:audio_book_app/providers/audio.dart';
import 'package:provider/provider.dart';
 
class AudioList extends StatelessWidget {
  const AudioList({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    final List<Audio> audios = Provider.of<List<Audio>>(context);
 
    return ListView.builder(
      itemCount: audios.length,
      itemBuilder: (context, index) {
        final audio = audios[index];
        return ListTile(
          leading: Image.network(
            audio.bookImage,
            width: 50,
            height: 50,
          ),
          title: Text(audio.audioName),
          subtitle: Text(audio.audioName),
          onTap: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => AudioPage(),
              ),
            );
          },
        );
      },
    );
  }
}

This is my audioplayerscreen.dart:


import 'package:audio_book_app/screens/audio_page_screen.dart';
import 'package:audio_book_app/widgets/audio_list.dart';
import 'package:flutter/material.dart';
import 'package:audio_book_app/providers/audios.dart';
import 'package:audio_book_app/widgets/app_drawer.dart';
import 'package:provider/provider.dart';
 
class AudioPlayerScreen extends StatefulWidget {
  final int bookId;
 
  AudioPlayerScreen({required this.bookId});
  static const routeName = '/audioplayerscreen';
 
  @override
  State<AudioPlayerScreen> createState() => _AudioPlayerScreenState();
}
 
class _AudioPlayerScreenState extends State<AudioPlayerScreen> {
  late final dynamic audiosprovider;
  late List audioFiles = [];
  bool isPlaying = false;
  // Duration duration = Duration.zero;
  // Duration position = Duration.zero;
 
  @override
  void initState() {
    super.initState();
    audiosprovider = Provider.of<Audios>(context, listen: false);
    final bookId = ModalRoute.of(context)!.settings.arguments as int;
    audioFiles = audiosprovider.getAudioFilesById(bookId);
  }
 
  void goToAudio(int audioIndex) {
    // update current audio index
    audiosprovider.currentAudioIndex = audioIndex;
 
    // navigate to song page
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => AudioPage(),
      ),
    );
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: const Color.fromARGB(255, 243, 243, 243),
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: const Text('My Library'),
        ),
        drawer: AppDrawer(),
        body: ListView.builder(
          itemCount: audioFiles.length,
          itemBuilder: (context, index) {
            return AudioList();
          },
        ));
  }
}  

This is my main.dart:


import 'package:audio_book_app/providers/audios.dart';
import 'package:audio_book_app/providers/books.dart';
import 'package:audio_book_app/screens/audio_player_screen.dart';
import 'package:audio_book_app/screens/convertin_screen.dart';
import 'package:audio_book_app/screens/home_screen.dart';
import 'package:audio_book_app/screens/login_screen.dart';
import 'package:audio_book_app/screens/logout_screen.dart';
import 'package:audio_book_app/screens/mylibrary_screen.dart';
import 'package:audio_book_app/screens/signup_screen.dart';
// import 'package:audio_book_app/screens/splash_screen.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import './providers/auth.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({super.key});
 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (ctx) => Auth(),
        ),
        ChangeNotifierProvider(
          create: (ctx) => Books(),
        ),
        ChangeNotifierProvider(
          create: (ctx) => Audios(),
        ),
      ],
      child: Consumer<Auth>(
          builder: (ctx, auth, _) => MaterialApp(
                  title: 'Audify',
                  theme: ThemeData(
                    colorScheme: ColorScheme.fromSeed(
                        seedColor: Colors.orange, secondary: Colors.deepOrange),
                    primaryColor: Colors.orange,
                    useMaterial3: true,
                  ),
                  home: auth.isAuth
                      ? const HomeScreen()
                      // : FutureBuilder(
                      // future: auth.tryAutoLogin(),
                      // builder: (ctx, authResultSnapshot) =>
                      // authResultSnapshot.connectionState ==
                      // ConnectionState.waiting
                      // ? SplashScreen()
                      : AuthScreen(),
                  // ),
                  routes: {
                    HomeScreen.routeName: (ctx) => const HomeScreen(),
                    ConvertingScreen.routeName: (ctx) =>
                        const ConvertingScreen(),
                    LogoutScreen.routeName: (ctx) => const LogoutScreen(),
                    MyLibraryScreen.routeName: (ctx) => const MyLibraryScreen(),
                    SignUpScreen.routeName: (ctx) => SignUpScreen(),
                    AuthScreen.routeName: (ctx) => AuthScreen(),
                      // I also need to pass the bookId here
                    AudioPlayerScreen.routeName: (ctx) => AudioPlayerScreen()
                  })),
    );
  }
}

Please let me know if there are more screens you need to see.

I expect the audioFiles of the selected book to be displayed but in my implementation, I am not able to pass the bookId from the selected book in the previous page as seen below:

mylibraryscreen.dart:

import 'package:audio_book_app/providers/auth.dart';
import 'package:audio_book_app/providers/books.dart';
import 'package:audio_book_app/widgets/app_drawer.dart';
import 'package:audio_book_app/widgets/mylibrary.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class MyLibraryScreen extends StatefulWidget {
  const MyLibraryScreen({super.key});
  static const routeName = '/mylibrary';

  @override
  State<MyLibraryScreen> createState() => _MyLibraryScreenState();
}

class _MyLibraryScreenState extends State<MyLibraryScreen> {
  // ignore: unused_field
  var _isInit = true;
  // ignore: unused_field
  var _isLoading = false;

  @override
  void initState() {
    setState(() {
      _isLoading = true;
    });
    _isLoading = true;
    final authData = Provider.of<Auth>(context, listen: false);
    Provider.of<Books>(context, listen: false)
        .fetchAndSetBooks(authData.token)
        .then((_) {
      setState(() {
        _isLoading = false;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final booksData = Provider.of<Books>(context);
    final books = booksData.items;
    return Scaffold(
      backgroundColor: const Color.fromARGB(255, 243, 243, 243),
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('My Library'),
      ),
      drawer: AppDrawer(),
      body: ListView.builder(
        itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
          value: books[i],
          child: const MyLibrary(),
        ),
        itemCount: books.length,
      ),
    );
  }
}

mylibrary.dart:

// import 'package:audio_book_app/providers/audios.dart';
import 'package:audio_book_app/providers/book.dart';
import 'package:audio_book_app/screens/audio_player_screen.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class MyLibrary extends StatelessWidget {
  const MyLibrary({super.key});

  @override
  Widget build(BuildContext context) {
    final book = Provider.of<Book>(context, listen: false);
    // final audiosProvider = Provider.of<Audios>(context);
    return Stack(
      alignment: Alignment.centerLeft,
      children: [
        Container(
          margin: const EdgeInsets.symmetric(vertical: 45, horizontal: 18),
          width: 550,
          height: 100,
          color: Colors.white,
        ),
        Positioned(
          child: Image.network(
            book.bookImage, // Replace with your image asset path
            width: 180,
            height: 130,
          ),
        ),
        Positioned(
          left: 200,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              FadeTransition(
                opacity:
                    const AlwaysStoppedAnimation(1), // Adjust opacity as needed
                child: SizedBox(
                  width: 130,
                  child: Text(
                    book.bookName,
                    overflow: TextOverflow.ellipsis,
                    maxLines: 2,
                    style: const TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
              ),
              const Text("John Smith"),
            ],
          ),
        ),
        Positioned(
          left: 330,
          top: 70,
          child: IconButton(
            onPressed: () {
              Navigator.of(context).pushReplacementNamed(
                AudioPlayerScreen.routeName,
                arguments: book.bookId,
              );
            },
            icon: const Icon(
              Icons.play_circle_fill_rounded,
              color: Colors.orange,
              size: 50,
            ),
          ),
        ),
      ],
    );
  }
}

0

There are 0 answers