Skip to main content

Build Music Player in Flutter


In this tutorial, we have covered the essential steps required to build a music player app using Flutter. By following this step-by-step guide, you should have a solid understanding of how to design the UI, implement audio playback functionality, manage app state, and add additional features to your app. With Flutter's cross-platform capabilities, you can create a music player app that runs on Android devices.


App common functionalities:
  • Audio Playback: The ability to play audio files in various formats, such as MP3.
  • Play Controls: Standard playback controls like play, pause, stop, skip forward, skip backward, and repeat.
  • Shuffle: Randomly play songs in a playlist.
  • Background Playback: Allowing users to continue playing music even when the app is running in the background or the device is locked.
  • Widgets and Notifications: Providing widgets or notifications for quick access to playback controls from the device's home screen or notification panel.


Step by step implementation

Step 1:   

To build this app, you require the following tools:
  1. Visual Studio Code (Recommended IDE)
  2. Android Emulator / Original Device for testing.
  3. Flutter SDK
  4. Flutter Plugin for VS Code.

Note: I use VS Code IDE in this tutorial.

Step 2:   
To create a new Flutter project using the flutter create command, follow these steps:
  1. Open your preferred command-line interface.
  2. Navigate to the directory where you want to create the Flutter project.
  3. Run the following command:
 
    flutter create Create_flutter_music_player


Step 3:   
To run project using the Visual Studio Code editor, follow these steps:
  1. Open VS Code on your computer.
  2. Click on "Open Folder" or go to "File" → "Open Folder" in the menu bar.
  3. Navigate to the directory where you created your Flutter project.
  4. Select the project folder and click "Open."
  5. Once the project is open in VS Code, open the terminal within VS Code by going to "View" → "Terminal" or using the keyboard shortcut (Ctrl+).
  6. In the terminal, make sure you are in the root directory of your project.
  7. To run the project, use the following command:
flutter run


Step 4:   

To add dependencies/packages to project, follow these steps:
  1. Open your project in Visual Studio code editor.
  2. Locate the pubspec.yaml file in the root directory of your Flutter project.
  3. Open the pubspec.yaml file.
  4. In the dependencies section of the pubspec.yaml file, add the following packages:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  just_audio: ^0.9.18
  just_audio_background: ^0.0.1-beta.1
  audio_service: ^0.18.1
  audio_session: ^0.1.6+1
  rxdart: ^0.27.2
  path: ^1.8.0
  path_provider: ^2.0.0
  async: ^2.5.0
  uuid: ^3.0.1
  crypto: ^3.0.0
  meta: ^1.3.0
  just_audio_libwinmedia: ^0.0.4
  provider: ^6.0.4
  shared_preferences: ^2.0.15
  font_awesome_flutter: ^10.3.0
  share: ^2.0.4
  url_launcher: ^6.1.7
  flutter_launcher_icons: ^0.11.0
  easy_splash_screen: ^1.0.4
  background_app_bar: ^2.1.0


Step 5:  

To get and download packages from project's dependencies you can use the flutter pub get command. Here's how:
  1. Open your preferred command-line interface.
  2. Navigate to the root directory of your project, where the pubspec.yaml file is located.
  3. Run the following command: 
flutter pub get

        
Step 6:   
To use the following permissions in the AndroidManifest.xml file modify the file directly. Here's how you can do it:
  1. Navigate to the android/app/src/main/ directory.
  2. Locate the AndroidManifest.xml file within the main directory.
  3. Open the AndroidManifest.xml file.
  4. Inside the <manifest> tag, add the following lines to specify the required permissions:

   <uses-permission android:name="android.permission.WAKE_LOCK"/>
   <uses-permission
       android:name="android.permission.FOREGROUND_SERVICE"/>
   <uses-permission android:name="android.permission.INTERNET" />


Step 7:  

Save the AndroidManifest.xml file. After making changes to the AndroidManifest.xml file, you can run project use the following command in the terminal within the project directory:

 
flutter run


Step 8:   

The main.dart file in Flutter is the entry point of your Flutter application. To replace the following code in the main.dart file of your project, follow these step-by-step instructions:
  1. Locate the main.dart file within the lib directory.
  2. Open the main.dart file.
  3. Select and copy the following code.
  4. Replace the existing code with the new code that you want to use.
  5. Save the main.dart file.


  import
'package:Creeate_flutter_music_player/consts/app_titles.dart';
  import
'package:Creeate_flutter_music_player/consts/theme_data.dart';
  import
'package:Creeate_flutter_music_player/pages/splash_screen.dart';
  import
'package:Creeate_flutter_music_player/provider/
  app_theme_provider.dart';
  import
'package:Creeate_flutter_music_player/widgets/app_drawer.dart';
  import 'package:flutter/material.dart';
  import 'package:just_audio_background/just_audio_background.dart';
  import 'package:provider/provider.dart';

  Future<void> main() async {
    await JustAudioBackground.init(
      androidNotificationChannelId:
        'com.ryanheise.bg_demo.channel.audio',
      androidNotificationChannelName: appBarTitle,
      androidNotificationOngoing: true,
      notificationColor: const Color(0xFF1a1a1a),
    );
    runApp(const MyApp());
  }

  class MyApp extends StatefulWidget {
    const MyApp({Key? key}) : super(key: key);
    @override
    _MyAppState createState() => _MyAppState();
  }

  class _MyAppState extends State<MyApp>
    with WidgetsBindingObserver {
    // Dark and Light Theme Start
    AppThemeProvider appThemeProvider = AppThemeProvider();

    void getCurrentAppTheme() async {
      appThemeProvider.setDarkTheme =
          await appThemeProvider.appThemeService.getTheme();
    }

    @override
    void initState() {
      getCurrentAppTheme();
      super.initState();
    }

  // Dark and Light Theme End
    @override
    Widget build(BuildContext context) {
  // Dark and Light Theme Start
      return MultiProvider(
        providers: [
          ChangeNotifierProvider(
            create: (_) {
              return appThemeProvider;
            },
          ),
        ],
        child: Consumer<AppThemeProvider>(
          builder: (context, themeprovider, child) {
            return MaterialApp(
              debugShowCheckedModeBanner: false,
              theme: MyStyles.themeData(
                themeprovider.getDarkTheme,
                context,
              ),
              // Dark and Light Theme End
              initialRoute: '/',
              title: 'MP3 Player',
              routes: {
                '/': (context) => const SplashScreenStart(),
                'appDrawer': (context) => const AppDrawer(),
              },
            );
          },
        ),
      );
    }
  }


Step 9:   

To create a splash screen you can follow these step-by-step instructions:
  1. Create pages folder in lib directory.
  2. Create a new Dart file, such as splash_screen.dart, to define your splash screen widget.
  3. Import the necessary packages.
  4. In your main.dart file, import the splash_screen.dart file:


  import
  'package:Creeate_flutter_music_player/consts/all_images.dart';
  import
  'package:Creeate_flutter_music_player/pages/home_page.dart';
  import 'package:easy_splash_screen/easy_splash_screen.dart';
  import 'package:flutter/material.dart';

  class SplashScreenStart extends StatelessWidget {
    const SplashScreenStart({
      Key? key,
    }) : super(key: key);

    @override
    Widget build(BuildContext context) {
      return EasySplashScreen(
        logo: Image.asset(
          defaultImg,
        ),
        logoWidth: 80,
        title: const Text(
          "MP3 Player",
          style: TextStyle(
            fontSize: 28,
            color: Colors.white,
            fontWeight: FontWeight.w900,
            fontFamily: "Tahoma",
          ),
        ),
        backgroundImage: Image.asset(
          splash,
        ).image,
        showLoader: true,
        loaderColor: Colors.teal.shade200,
        loadingText: Text(
          "ZEYARMAL",
          style: TextStyle(
            fontSize: 16,
            fontWeight: FontWeight.w900,
            fontFamily: "Tahoma",
            color: Colors.green.shade600,
          ),
        ),
        navigator: const HomePage(),
        durationInSeconds: 8,
      );
    }
  }



Step 10:  

To create an assets folder in your project and add it to the pubspec.yaml file, follow these steps:
  1. In the root directory of your project, create a new folder called assets. This is where you'll store your asset files.
  2. Place assets folder.
  3. Open the pubspec.yaml file located in the root directory of your project.
  4. In the pubspec.yaml file, locate the flutter section.
  5. Under the flutter section, add an assets entry with a list of the asset file paths relative to the assets folder. Use the YAML list format with a hyphen (-) before each asset path.
  6. Save the pubspec.yaml file.

flutter:
assets:
    - assets/


Step 11:  

After adding the assets folder and updating the pubspec.yaml file, you need to run the following command in your command-line interface within the project directory to ensure the assets are correctly configured:

flutter pub get

   
Step 12:   
To add custom titles to project, you can follow these steps:
  1. Create consts folder in lib directory.
  2. Then create a new Dart file in your project's lib/consts directory or any other appropriate directory. 
  3. This file will contain the code for your custom title widget.
  4. create a file named app_titles.dart.
  5. In the app_titles.dart file, define your app titles.
  6. Here's of titles:

  const String appBarTitle = "MP3 Player";
  const String previous = "Previous";
  const String play = "Play";
  const String pause = "Pause";
  const String replay = "Replay";
  const String next = "Next";
  const String repeat = "Repeat";
  const String adjustVolume = "Adjust Volume";
  const String adjustSpeed = "Adjust Speed";
  const String shuffle = "Shuffle";
  const String themeMode = "Theme Mode";


Step 13:   

To create custom styles for project, you can follow these steps:
  1. Create a new Dart file in your project's lib/consts directory or any other appropriate directory.
  2. create a file named app_text_styles.dart.
  3. In the app_text_styles.dart file, define your custom styles as static constants or functions. 
  4. Copy the following styles and paste it in your project styles directory:

  import 'package:flutter/material.dart';

  const fontWeightW500 = TextStyle(
    fontWeight: FontWeight.w500,
  );

  const fontWeightBold = TextStyle(
    fontWeight: FontWeight.bold,
  );

  const fontSize18Bold = TextStyle(
    fontSize: 18,
    fontWeight: FontWeight.bold,
  );

  const developerText = TextStyle(
    fontSize: 16,
    height: 1.6,
    fontWeight: FontWeight.w800,
  );

  const fontSize16 = TextStyle(
    fontSize: 16.0,
  );

  const fontSize24Bold = TextStyle(
    fontFamily: 'Fixed',
    fontWeight: FontWeight.bold,
    fontSize: 24.0,
  );

  const ellipsis = TextOverflow.ellipsis;

  const size0 = 0.0;
  const size0Point5 = 0.5;
  const size0Point8 = 0.8;
  const size1 = 1.0;
  const size1Point5 = 1.5;
  const size1Point65 = 1.65;
  const size1Point83 = 1.83;
  const size2 = 2.0;
  const size3Point5 = 3.5;
  const size5 = 5.0;
  const size6 = 6.0;
  const size4 = 4.0;
  const size10 = 10.0;
  const size8 = 8.0;
  const size13 = 13.0;
  const size14 = 14.0;
  const size15 = 15.0;
  const size16 = 16.0;
  const size18 = 18.0;
  const size20 = 20.0;
  const size24 = 24.0;
  const size40 = 40.0;
  const size44 = 44.0;
  const size50 = 50.0;
  const size60 = 60.0;
  const size100 = 100.0;
  const size120 = 120.0;
  const size300 = 300.0;
  const size540 = 540;
  int size_10 = 10;


Import the app_text_styles.dart file at the top of the Dart file where you want to use the custom styles.

Step 14:   

To create a custom colors file, you can follow these steps:
  1. Create a new Dart file in your project's lib/consts directory.
  2. Create a file named app_color.dart.
  3. Then, use the custom colors in your project:

  import 'dart:ui';

  const Color surahNoDark = Color(0xFF2B2A2A);
  const Color surahNoLight = Color(0xFF057575);
  const Color whiteColor = Color(0xFFFFFFFF);
  const Color shuffleActive = Color(0xFFFF9800);
  const Color shuffleInactive = Color(0xFF9E9E9E);


Step 15:   

To make images into one file and directory, you can follow these steps:

  1. Create a new dart file for custom image named all_images.dart file in your project's lib/consts directory or any other appropriate location.
  2. In the all_images.dart file, define your custom image variables. Each variable should represent a custom image and should be assigned the corresponding image path.
  3. Here's an example of defining custom image variables:


  const defaultImg = 'assets/web_hi_res_512.png';
  const bg = 'assets/bg-app.jpg';
  const splash = 'assets/splash.jpg';



Step 16:   

The home page refers to the main screen or initial screen that is displayed when the app is launched. It is the primary interface where users interact with the app's features and navigate to different sections or screens. The home page typically contains the main content and user interface elements of the app. It serves as the entry point for users and sets the foundation for the overall user experience. Remember to customize the design and functionality according to your specific needs and preferences.


  import 'package:audio_session/audio_session.dart';
  import 'package:background_app_bar/background_app_bar.dart';
  import 'package:flutter/foundation.dart';
  import 'package:flutter/material.dart';
  import 'package:flutter/services.dart';
  import 'package:just_audio/just_audio.dart';
  import 'package:just_audio_background/just_audio_background.dart';
  import 'package:provider/provider.dart';
  import 'package:rxdart/rxdart.dart';
  import
'package:Creeate_flutter_music_player/consts/all_images.dart';
  import
'package:Creeate_flutter_music_player/consts/app_color.dart';
  import
'package:Creeate_flutter_music_player/consts/app_text_styles.dart';
  import
'package:Creeate_flutter_music_player/consts/app_titles.dart';
  import
'package:Creeate_flutter_music_player/provider/
app_theme_provider.dart';
  import
'package:Creeate_flutter_music_player/widgets/app_drawer.dart';
  import
'package:Creeate_flutter_music_player/widgets/common.dart';

  class HomePage extends StatefulWidget {
    const HomePage({Key? key}) : super(key: key);
    @override
    _HomePageState createState() => _HomePageState();
  }

  class _HomePageState extends State<HomePage>
    with WidgetsBindingObserver {
    static int _nextMediaId = 0;
    static const _quranAudioUrl =
        'https://server11.mp3quran.net/sds/';
    static int _increasNum1 = 1;
    static int _increasNum10 = 10;
    late AudioPlayer _player;

   
    @override
    void initState() {
      super.initState();
      WidgetsBinding.instance.addObserver(this);
      _player = AudioPlayer();
      SystemChrome.setSystemUIOverlayStyle(
      const SystemUiOverlayStyle(
        statusBarColor: Color(0xFF121F1F),
      ));
      _init();
    }

    Future<void> _init() async {
      final session = await AudioSession.instance;
      await session.configure(
            const AudioSessionConfiguration.speech());
      // Listen to errors during playback.
      _player.playbackEventStream.listen((event) {},
          onError: (Object e, StackTrace stackTrace) {
        // ignore: avoid_print
        print('A stream error occurred: $e');
      });
      try {
        // Preloading audio is not currently supported on Linux.
        await _player.setAudioSource(_playlist,
            preload: kIsWeb || defaultTargetPlatform !=
                TargetPlatform.linux);
      } catch (e) {
        // Catch load errors: 404, invalid url...
        // ignore: avoid_print
        print("Error loading audio source: $e");
      }
    }

    @override
    void dispose() {
      WidgetsBinding.instance.removeObserver(this);
      _player.dispose();
      super.dispose();
    }

    Stream<PositionData> get _positionDataStream =>
        Rx.combineLatest3<Duration, Duration, Duration?,
            PositionData>(
            _player.positionStream,
            _player.bufferedPositionStream,
            _player.durationStream,
            (position, bufferedPosition, duration) =>
                PositionData(
                position, bufferedPosition, duration ??
                Duration.zero));

    @override
    Widget build(BuildContext context) {
      final double screenWidth = MediaQuery.of(context).size.width;
      final double screenHeight =
        MediaQuery.of(context).size.height;
      final bgColor = Theme.of(context).primaryColor;
      final themeState = Provider.of<AppThemeProvider>(context);

      return Scaffold(
        drawer: const AppDrawer(),
        body: NestedScrollView(
          headerSliverBuilder: (final _, final __) => <Widget>[
            SliverAppBar(
              centerTitle: true,
              expandedHeight: 210,
              floating: false,
              pinned: true,
              snap: false,
              elevation: 0.0,
              backgroundColor: Colors.transparent,
              flexibleSpace: BackgroundFlexibleSpaceBar(
                expandedTitleScale: 1.8,
                title: const Text(
                  appBarTitle,
                  style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.w900,
                  ),
                ),
                centerTitle: true,
                background: ClipRect(
                  child: Container(
                    decoration: const BoxDecoration(
                      image: DecorationImage(
                        image: AssetImage(bg),
                        fit: BoxFit.cover,
                      ),
                    ),
                    child: Container(
                      decoration: BoxDecoration(
                        color: themeState.getDarkTheme
                            ? Colors.black26
                            : Colors.white.withOpacity(0.2),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ],
          body: Stack(
            children: [
              Positioned(
                top: size0,
                right: size0,
                left: size0,
                bottom: screenWidth > size540 ? 106 : 160,
                // ignore: sized_box_for_whitespace
                child: Container(
                  height: screenHeight,
                  child: StreamBuilder<SequenceState?>(
                    stream: _player.sequenceStateStream,
                    builder: (context, snapshot) {
                      final state = snapshot.data;
                      final sequence = state?.sequence ?? [];
                      return ListView(
                        padding: const EdgeInsets.all(0),
                        children: [
                          for (var i = 0; i < sequence.length; i++)
                            Container(
                              decoration: BoxDecoration(
                                border: Border(
                                  bottom: BorderSide(
                                    width: 0.5,
                                    color:
                                    Theme.of(context).cardColor,
                                  ),
                                ),
                              ),
                              key: ValueKey(sequence[i]),
                              child: Column(
                                children: [
                                  Material(
                                    color: i == state!.currentIndex
                                    ? Theme.of(context).cardColor
                                    : Colors.transparent,
                                    child: ListTile(
                                      leading: CircleAvatar(
                                    backgroundColor:
                                        themeState.getDarkTheme
                                            ? surahNoDark
                                            : surahNoLight,
                                        child:
                                        Text(sequence[i].tag.album,
                                        style: fontWeightW500),
                                      ),
                                      title: Text(
                                        sequence[i].tag.title
                                            as String,
                                        style: fontSize18Bold,
                                        overflow: ellipsis,
                                      ),
                                      trailing: Text(
                                        sequence[i].tag.artist
                                            as String,
                                        style: fontSize18Bold,
                                        overflow: ellipsis,
                                      ),
                                      onTap: () {
                                        _player.seek(Duration.zero,
                                                         index: i);
                                      },
                                    ),
                                  ),
                                ],
                              ),
                            ),
                        ],
                      );
                    },
                  ),
                ),
              ),
              Positioned(
                bottom: 0,
                left: 0,
                right: 0,
                child: Container(
                  height: screenWidth > size540 ? 110 : 160,
                  padding: EdgeInsets.only(
                    top: screenWidth > size540 ? 24 : size4,
                  ),
                  color: themeState.getDarkTheme
                                ? bgColor : whiteColor,
                  child: Column(
                    children: [
                      screenWidth > size540
                          ? Container()
                          : StreamBuilder<SequenceState?>(
                              stream: _player.sequenceStateStream,
                              builder: (context, snapshot) {
                                final state = snapshot.data;
                                if (state?.sequence.isEmpty
                                                    ?? true) {
                                  return const Center(
                                    child:
                                    CircularProgressIndicator(),
                                  );
                                }
                                final metadata =
                        state!.currentSource!.tag as MediaItem;
                                return SizedBox(
                                  width: double.infinity,
                                  child: Row(
                                    mainAxisAlignment:
                                    MainAxisAlignment.spaceBetween,
                                    children: [
                                    ControlVolumeButtons(_player),
                                      Row(
                                        children: [
                                          Text(
                                         metadata.album.toString(),
                                         style: fontSize18Bold,
                                          ),
                                          const Text(
                                            ' - ',
                                          ),
                                          Text(
                                            metadata.title,
                                            style: fontSize18Bold,
                                          ),
                                        ],
                                      ),
                                      ControlAdjustSpeedButtons(
                                        _player
                                      ),
                                    ],
                                  ),
                                );
                              },
                            ),
                      Container(
                        color: Colors.transparent,
                        height: size24,
                        margin: screenWidth > size540
                            ? const EdgeInsets.only(
                                top: size0,
                              )
                            : const EdgeInsets.only(
                                top: size16,
                              ),
                        child: StreamBuilder<PositionData>(
                          stream: _positionDataStream,
                          builder: (context, snapshot) {
                            final positionData = snapshot.data;
                            return SeekBar(
                              duration: positionData?.duration
                                ?? Duration.zero,
                              position: positionData?.position
                                ?? Duration.zero,
                              bufferedPosition:
                                  positionData?.bufferedPosition
                                ?? Duration.zero,
                              onChangeEnd: (newPosition) {
                                _player.seek(newPosition);
                              },
                            );
                          },
                        ),
                      ),
                      screenWidth > size540
                          ? Container()
                          : ControlButtons(_player),
                      screenWidth > size540
                          ? Row(
                              mainAxisAlignment:
                                MainAxisAlignment.spaceBetween,
                              children: [
                                Container(
                                  margin: const EdgeInsets.only(
                                    left: size14,
                                    bottom: size8,
                                  ),
                                  child:
                                    ControlButtonsSecond(_player),
                                ),
                                SizedBox(
                                  width: screenWidth / size3Point5,
                                  child:
                                    StreamBuilder<SequenceState?>(
                                    stream:
                                       _player.sequenceStateStream,
                                    builder: (context, snapshot) {
                                      final state = snapshot.data;
                                      if (state?.sequence.isEmpty
                                           ?? true) {
                                        return const Center(
                                          child:
                                       CircularProgressIndicator(),
                                        );
                                      }
                                      final metadata =
                                     state!.currentSource!.tag
                                        as MediaItem;
                                      return Row(
                                       mainAxisAlignment:
                                        MainAxisAlignment.center,
                                        children: [
                                          Text(
                                          metadata.album.toString(),
                                          style: fontSize18Bold,
                                          ),
                                          const Text(
                                            ' - ',
                                          ),
                                          Text(
                                            metadata.title,
                                            style: fontSize18Bold,
                                            overflow: ellipsis,
                                          ),
                                        ],
                                      );
                                    },
                                  ),
                                ),
                                Container(
                                  margin: const EdgeInsets.only(
                                    right: size14,
                                    bottom: size8,
                                  ),
                                  child:
                                    ColLgControlButtons(_player),
                                ),
                              ],
                            )
                          : Container(),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      );
    }
  }


Step 17:   

Audio playback is a common feature in many Flutter applications, and Flutter provides powerful tools like the ConcatenatingAudioSource and AudioSource classes to handle audio concatenation efficiently and deliver a smooth user experience. Copy the following data list and paste in the home_page.dart file.

    
    final _playlist = ConcatenatingAudioSource(
      children: [
        if (kIsWeb ||
            ![TargetPlatform.windows, TargetPlatform.linux]
                .contains(defaultTargetPlatform))
          AudioSource.uri(
            Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
            tag: MediaItem(
              id: '${_nextMediaId++}',
              title: "AlFatiha",
              album: "001",
              artist: "الفَاتِحَة",
            ),
          ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "AlBaqara",
            album: "002",
            artist: "البَقَرَة",
          ),
        ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "AalEImran",
            album: "003",
            artist: "آلِ عِمْرَان",
          ),
        ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "AnNisa",
            album: "004",
            artist: "النِّسَاء",
          ),
        ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "AlMaidah",
            album: "005",
            artist: "المَائِدَة",
          ),
        ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "AlAnaam",
            album: "006",
            artist: "الأَنْعَام",
          ),
        ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "AlAraf",
            album: "007",
            artist: "الأَعْرَاف",
          ),
        ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "AlAnfal",
            album: "008",
            artist: "الأَنْفَال",
          ),
        ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}00${_increasNum1++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "AtTawba",
            album: "009",
            artist: "التَّوْبَة",
          ),
        ),
        AudioSource.uri(
          Uri.parse('${_quranAudioUrl}0${_increasNum10++}.mp3'),
          tag: MediaItem(
            id: '${_nextMediaId++}',
            title: "Yunus",
            album: "010",
            artist: "يُونُس",
          ),
        ),
      ],
    );


Step 18:   

Implementing control buttons for an MP3 player in Flutter allows users to interact with audio playback features conveniently. By leveraging Flutter's widget library, integrating an audio player package, and applying state management techniques. Integrate the control buttons with the audio player package to control audio playback. Utilize functions from the audio player package, such as play(), pause(), stop(), seek(), or next(), to perform relevant actions when the buttons are pressed. Connect the buttons to the appropriate functions using onPressed callbacks. Copy the following codes and paste in the home_page.dart file.

    // on during of play or pause
    class ControlLineProgress extends StatelessWidget {
      final AudioPlayer player;

      const ControlLineProgress(this.player, {Key? key}) :
         super(key: key);

      @override
      Widget build(BuildContext context) {
        return StreamBuilder<PlayerState>(
          stream: player.playerStateStream,
          builder: (context, snapshot) {
            final playerState = snapshot.data;
            final processingState = playerState?.processingState;
            // final playing = playerState?.playing;
            if (processingState == ProcessingState.loading ||
                processingState == ProcessingState.buffering) {
              return Container(
                width: size60,
                margin: const EdgeInsets.only(
                  top: size10,
                ),
                child: const LinearProgressIndicator(),
              );
            } else {
              return const SizedBox();
            }
          },
        );
      }
    }

    // internet check

    // Previous, next and controll buttons
    class ControlButtons extends StatefulWidget {
      final AudioPlayer player;

      const ControlButtons(this.player, {Key? key}) :
            super(key: key);

      @override
      State<ControlButtons> createState() => _ControlButtonsState();
    }

    class _ControlButtonsState extends State<ControlButtons> {
      @override
      Widget build(BuildContext context) {
        return Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            // === shuffle button start
            StreamBuilder<bool>(
              stream: widget.player.shuffleModeEnabledStream,
              builder: (context, snapshot) {
                final shuffleModeEnabled = snapshot.data ?? false;
                return IconButton(
                  icon: shuffleModeEnabled
                      ? const Icon(Icons.shuffle,
                            color: shuffleActive)
                      : const Icon(Icons.shuffle,
                            color: shuffleInactive),
                  tooltip: shuffle,
                  onPressed: () async {
                    final enable = !shuffleModeEnabled;
                    if (enable) {
                      await widget.player.shuffle();
                    }
                    await
                    widget.player.setShuffleModeEnabled(enable);
                  },
                );
              },
            ),
            // === shuffle button end
            Row(
              children: [
                // === Previous button start
                StreamBuilder<SequenceState?>(
                  stream: widget.player.sequenceStateStream,
                  builder: (context, snapshot) => IconButton(
                    icon: const Icon(Icons.skip_previous),
                    onPressed: widget.player.seekToPrevious,
                    tooltip: previous,
                  ),
                ),
                // === Previous button end
                // === Play and pause button start
                StreamBuilder<PlayerState>(
                  stream: widget.player.playerStateStream,
                  builder: (context, snapshot) {
                    final playerState = snapshot.data;
                    final processingState =
                        playerState?.processingState;
                    final playing = playerState?.playing;
                    if (processingState ==
                                ProcessingState.loading ||
                        processingState ==
                                ProcessingState.buffering) {
                      return Container(
                        margin: const EdgeInsets.symmetric(
                          horizontal: size10,
                        ),
                        height: size60,
                        width: size60,
                        child: const CircularProgressIndicator(),
                      );
                    } else if (playing != true) {
                      return Container(
                        margin: const EdgeInsets.symmetric(
                          horizontal: size10,
                        ),
                        child: IconButton(
                          icon: const Icon(
                            Icons.play_arrow,
                          ),
                          iconSize: size44,
                          onPressed: widget.player.play,
                          tooltip: play,
                        ),
                      );
                    } else if (processingState !=
                        ProcessingState.completed) {
                      return Container(
                        margin: const EdgeInsets.symmetric(
                          horizontal: size10,
                        ),
                        child: IconButton(
                          icon: const Icon(Icons.pause),
                          iconSize: size44,
                          onPressed: widget.player.pause,
                          tooltip: pause,
                        ),
                      );
                    } else {
                      return Container(
                        margin: const EdgeInsets.symmetric(
                          horizontal: size10,
                        ),
                        child: IconButton(
                          icon: const Icon(Icons.replay),
                          iconSize: size44,
                          onPressed: () =>
                            widget.player.seek(Duration.zero,
                              index:                            widget.player.effectiveIndices!.first),
                          tooltip: replay,
                        ),
                      );
                    }
                  },
                ),
                // === Play and pause button end

                // === Next button start
                StreamBuilder<SequenceState?>(
                  stream: widget.player.sequenceStateStream,
                  builder: (context, snapshot) => IconButton(
                    icon: const Icon(Icons.skip_next),
                    onPressed: widget.player.seekToNext,
                    tooltip: next,
                  ),
                ),
                // === Next button End
              ],
            ),
            // === Repeat button Start
            StreamBuilder<LoopMode>(
              stream: widget.player.loopModeStream,
              builder: (context, snapshot) {
                final loopMode = snapshot.data ?? LoopMode.off;
                const icons = [
                  Icon(Icons.repeat, color: shuffleInactive),
                  Icon(Icons.repeat, color: shuffleActive),
                  Icon(Icons.repeat_one, color: shuffleActive),
                ];
                const cycleModes = [
                  LoopMode.off,
                  LoopMode.all,
                  LoopMode.one,
                ];
                final index = cycleModes.indexOf(loopMode);
                return IconButton(
                  icon: icons[index],
                  onPressed: () {
                    widget.player.setLoopMode(cycleModes[
                        (cycleModes.indexOf(loopMode)
                            + 1) % cycleModes.length]);
                  },
                  tooltip: repeat,
                );
              },
            ),
            // === Shuffle button End
          ],
        );
      }
    }

    // max width size540
    class ColLgControlButtons extends StatefulWidget {
      final AudioPlayer player;

      const ColLgControlButtons(this.player, {Key? key}) :
        super(key: key);

      @override
      State<ColLgControlButtons> createState() =>
        _ColLgControlButtonsState();
    }

    class _ColLgControlButtonsState extends
                State<ColLgControlButtons> {
      @override
      Widget build(BuildContext context) {
        return Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            StreamBuilder<SequenceState?>(
              stream: widget.player.sequenceStateStream,
              builder: (context, snapshot) => IconButton(
                icon: const Icon(Icons.skip_previous),
                onPressed: widget.player.seekToPrevious,
                tooltip: previous,
              ),
            ),
            StreamBuilder<PlayerState>(
              stream: widget.player.playerStateStream,
              builder: (context, snapshot) {
                final playerState = snapshot.data;
                final processingState =
                         playerState?.processingState;
                final playing = playerState?.playing;
                if (processingState == ProcessingState.loading ||
                    processingState == ProcessingState.buffering)
                {
                  return Container(
                    margin: const EdgeInsets.symmetric(
                      horizontal: size10,
                    ),
                    height: size40,
                    width: size40,
                    child: const CircularProgressIndicator(),
                  );
                } else if (playing != true) {
                  return Container(
                    margin: const EdgeInsets.symmetric(
                      horizontal: size10,
                    ),
                    child: IconButton(
                      icon: const Icon(
                        Icons.play_arrow,
                      ),
                      onPressed: widget.player.play,
                      tooltip: play,
                    ),
                  );
                } else if (processingState !=
                            ProcessingState.completed) {
                  return Container(
                    margin: const EdgeInsets.symmetric(
                      horizontal: size10,
                    ),
                    child: IconButton(
                      icon: const Icon(Icons.pause),
                      onPressed: widget.player.pause,
                      tooltip: pause,
                    ),
                  );
                } else {
                  return Container(
                    margin: const EdgeInsets.symmetric(
                      horizontal: size10,
                    ),
                    child: IconButton(
                      icon: const Icon(
                        Icons.replay,
                      ),
                      onPressed: () =>
                        widget.player.seek(Duration.zero,
                          index:
                            widget.player.effectiveIndices!.first),
                      tooltip: replay,
                    ),
                  );
                }
              },
            ),
            StreamBuilder<SequenceState?>(
              stream: widget.player.sequenceStateStream,
              builder: (context, snapshot) => IconButton(
                icon: const Icon(Icons.skip_next),

                onPressed: widget.player.seekToNext,
                //  widget.player.hasNext ?
                // widget.player.seekToNext : null,
                tooltip: next,
              ),
            ),
          ],
        );
      }
    }

    // Volume
    class ControlVolumeButtons extends StatelessWidget {
      final AudioPlayer player;

      const ControlVolumeButtons(this.player, {Key? key}) :
        super(key: key);

      @override
      Widget build(BuildContext context) {
        return IconButton(
          icon: const Icon(Icons.volume_up),
          tooltip: adjustVolume,
          onPressed: () {
            showSliderDialog(
              context: context,
              title: adjustVolume,
              divisions: size_10,
              min: size0,
              max: size1,
              value: player.volume,
              stream: player.volumeStream,
              onChanged: player.setVolume,
            );
          },
        );
      }
    }

    // adjust speed
    class ControlAdjustSpeedButtons extends StatelessWidget {
      final AudioPlayer player;

      const ControlAdjustSpeedButtons(this.player, {Key? key}) :
        super(key: key);

      @override
      Widget build(BuildContext context) {
        return StreamBuilder<double>(
          stream: player.speedStream,
          builder: (context, snapshot) => IconButton(
            icon: Text(
              "${snapshot.data?.toStringAsFixed(1)}x",
              style: fontWeightBold,
            ),
            tooltip: adjustSpeed,
            onPressed: () {
              showSliderDialog(
                context: context,
                title: adjustSpeed,
                divisions: size_10,
                min: size0Point5,
                max: size1Point5,
                value: player.speed,
                stream: player.speedStream,
                onChanged: player.setSpeed,
              );
            },
          ),
        );
      }
    }

    // repeat volume, adjust speed and shuffle
    class ControlButtonsSecond extends StatelessWidget {
      final AudioPlayer player;

      const ControlButtonsSecond(this.player, {Key? key}) :
         super(key: key);

      @override
      Widget build(BuildContext context) {
        return Row(
          // mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            StreamBuilder<LoopMode>(
              stream: player.loopModeStream,
              builder: (context, snapshot) {
                final loopMode = snapshot.data ?? LoopMode.off;
                const icons = [
                  Icon(Icons.repeat, color: shuffleInactive),
                  Icon(Icons.repeat, color: shuffleActive),
                  Icon(Icons.repeat_one, color: shuffleActive),
                ];
                const cycleModes = [
                  LoopMode.off,
                  LoopMode.all,
                  LoopMode.one,
                ];
                final index = cycleModes.indexOf(loopMode);
                return Container(
                  margin: const EdgeInsets.only(
                    right: size5,
                  ),
                  child: IconButton(
                    icon: icons[index],
                    onPressed: () {
                      player.setLoopMode(cycleModes[
                          (cycleModes.indexOf(loopMode)
                           + 1) % cycleModes.length]);
                    },
                    tooltip: repeat,
                  ),
                );
              },
            ),
            Container(
              margin: const EdgeInsets.only(
                right: size5,
                left: size5,
              ),
              child: IconButton(
                icon: const Icon(Icons.volume_up),
                tooltip: adjustVolume,
                onPressed: () {
                  showSliderDialog(
                    context: context,
                    title: adjustVolume,
                    divisions: size_10,
                    min: size0,
                    max: size1,
                    value: player.volume,
                    stream: player.volumeStream,
                    onChanged: player.setVolume,
                  );
                },
              ),
            ),
            StreamBuilder<double>(
              stream: player.speedStream,
              builder: (context, snapshot) => Container(
                margin: const EdgeInsets.only(
                  right: size5,
                  left: size5,
                ),
                child: IconButton(
                  icon: Text(
                    "${snapshot.data?.toStringAsFixed(1)}x",
                    style: fontWeightBold,
                  ),
                  tooltip: adjustSpeed,
                  onPressed: () {
                    showSliderDialog(
                      context: context,
                      title: adjustSpeed,
                      divisions: size_10,
                      min: size0Point5,
                      max: size1Point5,
                      value: player.speed,
                      stream: player.speedStream,
                      onChanged: player.setSpeed,
                    );
                  },
                ),
              ),
            ),
            StreamBuilder<bool>(
              stream: player.shuffleModeEnabledStream,
              builder: (context, snapshot) {
                final shuffleModeEnabled = snapshot.data ?? false;
                return Container(
                  margin: const EdgeInsets.only(
                    right: size5,
                    left: size5,
                  ),
                  child: IconButton(
                    icon: shuffleModeEnabled
                        ? const Icon(
                            Icons.shuffle,
                            color: shuffleActive,
                        )
                        : const Icon(Icons.shuffle,
                           color: shuffleInactive),
                    tooltip: shuffle,
                    onPressed: () async {
                      final enable = !shuffleModeEnabled;
                      if (enable) {
                        await player.shuffle();
                      }
                      await player.setShuffleModeEnabled(enable);
                    },
                  ),
                );
              },
            ),
          ],
        );
      }
    }


Step 19:   

To create separate ThemeData instances for dark and light themes, you can follow these steps:
  1. Create a new Dart file in your project's lib/consts directory.
  2. create a file named theme_data.dart.
  3. Import the flutter/material.dart package in theme_data.dart file.
  4. By following MyStyles class , you can create separate ThemeData instances for dark and light themes:

  import 'package:flutter/material.dart';
  import 'package:flutter/services.dart';

  // Dark and Light Theme Start
  class MyStyles {
    static ThemeData themeData(
      bool isDarkTheme,
      BuildContext context,
    ) {
      return ThemeData(
        visualDensity: VisualDensity.adaptivePlatformDensity,
        appBarTheme: AppBarTheme(
          backgroundColor:
              isDarkTheme ?
                const Color(0xFF262626) :
                  Colors.grey.shade50,
          foregroundColor: isDarkTheme ?
            Colors.white :
            Colors.black,
          elevation: 3,
          systemOverlayStyle: const SystemUiOverlayStyle(
            statusBarColor: Colors.transparent,
          ),
        ),
        colorScheme: ThemeData().colorScheme.copyWith(
              secondary:
                  isDarkTheme ?
                  const Color(0xFF060C0C) :
                  const Color(0xffe8fdfd),
              brightness: isDarkTheme ?
              Brightness.dark :
              Brightness.light,
            ),
        cardTheme: CardTheme(
          elevation: 5,
          color: isDarkTheme ?
          const Color(0xFF102020) :
          const Color(0xFFE9DAE6),
        ),
        scaffoldBackgroundColor:
            isDarkTheme ?
            const Color(0xFF1a1a1a) :
            Colors.grey.shade100,
        primaryColor:
            isDarkTheme ?
            const Color(0xFF162424) :
            Colors.indigo.shade50,
        iconTheme:
            IconThemeData(color: isDarkTheme ?
            Colors.white :
            Colors.black),
        cardColor:
            isDarkTheme ?
            const Color(0xFF182929) :
            const Color(0xFFEECEEB),
        canvasColor: isDarkTheme ?
        const Color(0xFF121F1F) :
        Colors.grey.shade50,
        dividerColor:
            isDarkTheme ?
            const Color(0xFF222F2F) :
            Colors.grey.shade400,
        // primarySwatch: Colors.teal,

        sliderTheme: SliderThemeData(
          activeTrackColor:
              isDarkTheme ?
              Colors.red.shade500 :
              const Color(0xFF068D8D),
          trackHeight: 3,
          inactiveTrackColor:
              isDarkTheme ?
              Colors.red.shade300 :
              Colors.grey.shade300,
          thumbColor:
              isDarkTheme ?
              const Color(0xFFE40000) :
              const Color(0xFF057575),
          thumbShape: const RoundSliderThumbShape(
            enabledThumbRadius: 11,
          ),
        ),
      );
    }
  }
    // Dark and Light Theme End


Step 20:   

The provider allows you to switch between themes based on the current brightness mode. The ThemeProvider class handles the logic for updating the theme data and brightness, and the ChangeNotifierProvider ensures that widgets are updated when a theme change occurs.
  1. Create a new folder named provider in your project's lib directory.
  1. create a file named app_theme_provider.dart in proivder folder.
  1. By following AppThemeService class, you can create a theme provider that supports both dark and light themes in your app:

  import 'package:shared_preferences/shared_preferences.dart';
  // Dark and Light Theme Start

  class AppThemeService {
    static const themeStatus = "THEMESTATUS";

    setDarkTheme(bool value) async {
      SharedPreferences prefs =
        await SharedPreferences.getInstance();
      prefs.setBool(themeStatus, value);
    }

    Future<bool> getTheme() async {
      SharedPreferences prefs =
        await SharedPreferences.getInstance();
      return prefs.getBool(themeStatus) ?? false;
    }
  // Dark and Light Theme End

  }

Step 21:   

Create a class called AppThemeService to handle theme-related functionality. You can create a theme service that supports both dark and light themes.

  1. Create a new folder named services in your project's lib directory.
  2. create a file named app_theme_service.dart in services folder.
  3. By following AppThemeService class, you can create a theme service that supports both dark and light themes:


    import 'package:shared_preferences/shared_preferences.dart';
    // Dark and Light Theme Start

    class AppThemeService {
      static const themeStatus = "THEMESTATUS";

      setDarkTheme(bool value) async {
        SharedPreferences prefs =
            await SharedPreferences.getInstance();
        prefs.setBool(themeStatus, value);
      }

      Future<bool> getTheme() async {
        SharedPreferences prefs =
            await SharedPreferences.getInstance();
        return prefs.getBool(themeStatus) ?? false;
      }
    // Dark and Light Theme End

    }

Step 22:   

To create a drawer, you can import the required packages like 'package:flutter/material.dart' for using Flutter's material design widgets.
  1. Create a new folder named widgets in your project's lib directory.
  2. create a file named app_drawer.dart in widgets folder.
  3. Inside the Scaffold, set the drawer property to a Drawer widget.
  4. The Drawer widget contains the content that will be displayed when the user opens the drawer.
  5. Use the ListView widget to define the list of items in the drawer.


  import
'package:Creeate_flutter_music_player/consts/all_images.dart';
  import
'package:Creeate_flutter_music_player/consts/app_color.dart';
  import
'package:Creeate_flutter_music_player/consts/app_text_styles.dart';
  import
'package:Creeate_flutter_music_player/consts/app_titles.dart';
  import
'package:Creeate_flutter_music_player/provider/
app_theme_provider.dart';
  import 'package:flutter/material.dart';
  import
'package:font_awesome_flutter/font_awesome_flutter.dart';
  import 'package:provider/provider.dart';

  class AppDrawer extends StatelessWidget {
    const AppDrawer({Key? key}) : super(key: key);

    @override
    Widget build(BuildContext context) {
      final themeState = Provider.of<AppThemeProvider>(context);
      final bgColor = Theme.of(context).primaryColor;
      return Drawer(
        child: ListView(
          padding: const EdgeInsets.all(0),
          children: [
            DrawerHeader(
              decoration: BoxDecoration(
                image: DecorationImage(
                  opacity: themeState.getDarkTheme
                    ? size0Point8 : size1,
                  image: const AssetImage(bg),
                  fit: BoxFit.cover,
                ),
              ),
              child: Container(
                child: Text(
                  appBarTitle,
                  style: TextStyle(
                    fontSize: size24,
                    color: themeState.getDarkTheme
                       ? whiteColor : bgColor,
                  ),
                ),
                alignment: Alignment.center,
              ),
            ),
            SwitchListTile(
              activeColor: themeState.getDarkTheme
                ? whiteColor : bgColor,
              title: const Text(themeMode),
              secondary: FaIcon(
                themeState.getDarkTheme ?
                    Icons.dark_mode : Icons.light_mode,
              ),
              onChanged: (bool value) {
                themeState.setDarkTheme = value;
              },
              value: themeState.getDarkTheme,
            ),
          ],
        ),
      );
    }
  }



Step 23:   

To create common functionalites for a music player:
  1. Create a new Dart file in your project's lib/widgets directory.
  2. create a file named common.dart.
  3. Copy the code below and paste in the common.dart file.


  import 'dart:math';
  import
'package:Creeate_flutter_music_player/consts/app_text_styles.dart';
  import 'package:flutter/material.dart';

  class SeekBar extends StatefulWidget {
    final Duration duration;
    final Duration position;
    final Duration bufferedPosition;
    final ValueChanged<Duration>? onChanged;
    final ValueChanged<Duration>? onChangeEnd;

    const SeekBar({
      Key? key,
      required this.duration,
      required this.position,
      required this.bufferedPosition,
      this.onChanged,
      this.onChangeEnd,
    }) : super(key: key);

    @override
    _SeekBarState createState() => _SeekBarState();
  }

  class _SeekBarState extends State<SeekBar> {
    double? _dragValue;
    late SliderThemeData _sliderThemeData;

    @override
    void didChangeDependencies() {
      super.didChangeDependencies();

      _sliderThemeData = SliderTheme.of(context).copyWith(
        trackHeight: 2.0,
      );
    }

    @override
    Widget build(BuildContext context) {
      return Stack(
        children: [
          SliderTheme(
            data: _sliderThemeData.copyWith(
              thumbShape: HiddenThumbComponentShape(),
              activeTrackColor: Colors.blue.shade100,
              inactiveTrackColor: Colors.grey.shade300,
            ),
            child: ExcludeSemantics(
              child: Slider(
                min: 0.0,
                max: widget.duration.inMilliseconds.toDouble(),
                value: min(
                widget.bufferedPosition.inMilliseconds.toDouble(),
                    widget.duration.inMilliseconds.toDouble()),
                onChanged: (value) {
                  setState(() {
                    _dragValue = value;
                  });
                  if (widget.onChanged != null) {
                    widget.onChanged!(Duration(
                        milliseconds: value.round()
                    ));
                  }
                },
                onChangeEnd: (value) {
                  if (widget.onChangeEnd != null) {
                    widget.onChangeEnd!(Duration(
                        milliseconds: value.round()
                    ));
                  }
                  _dragValue = null;
                },
              ),
            ),
          ),
          SliderTheme(
            data: _sliderThemeData.copyWith(
              inactiveTrackColor: Colors.transparent,
            ),
            child: Slider(
              min: 0.0,
              max: widget.duration.inMilliseconds.toDouble(),
              value: min(_dragValue ??
                widget.position.inMilliseconds.toDouble(),
                  widget.duration.inMilliseconds.toDouble()),
              onChanged: (value) {
                setState(() {
                  _dragValue = value;
                });
                if (widget.onChanged != null) {
                  widget.onChanged!(Duration(
                    milliseconds: value.round()
                  ));
                }
              },
              onChangeEnd: (value) {
                if (widget.onChangeEnd != null) {
                  widget.onChangeEnd!(
                    Duration(milliseconds: value.round())
                  );
                }
                _dragValue = null;
              },
            ),
          ),
          Positioned(
            right: 23,
            child: Text(
              RegExp(r'((^0*[1-9]\d*:)?\d{2}:\d{2})\.\d+$')
                      .firstMatch("$_remaining")
                      ?.group(1) ??
                  '$_remaining',
              style: const TextStyle(
                height: 0.1,
              ),
            ),
          ),
        ],
      );
    }

    Duration get _remaining => widget.duration - widget.position;
  }

  class HiddenThumbComponentShape extends SliderComponentShape {
    @override
    Size getPreferredSize(
        bool isEnabled,
        bool isDiscrete
    ) => Size.zero;

    @override
    void paint(
      PaintingContext context,
      Offset center, {
      required Animation<double> activationAnimation,
      required Animation<double> enableAnimation,
      required bool isDiscrete,
      required TextPainter labelPainter,
      required RenderBox parentBox,
      required SliderThemeData sliderTheme,
      required TextDirection textDirection,
      required double value,
      required double textScaleFactor,
      required Size sizeWithOverflow,
    }) {}
  }

  class PositionData {
    final Duration position;
    final Duration bufferedPosition;
    final Duration duration;

    PositionData(
        this.position,
        this.bufferedPosition,
        this.duration,
    );
  }

  void showSliderDialog({
    required BuildContext context,
    required String title,
    required int divisions,
    required double min,
    required double max,
    String valueSuffix = '',
    required double value,
    required Stream<double> stream,
    required ValueChanged<double> onChanged,
  }) {
    showDialog<void>(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(
          title,
          textAlign: TextAlign.center,
        ),
        content: StreamBuilder<double>(
          stream: stream,
          builder: (context, snapshot) => SizedBox(
            height: size100,
            child: Column(
              children: [
                Text(
                  '${snapshot.data?.toStringAsFixed(1)}$valueSuffix',
                  style: fontSize24Bold,
                ),
                Slider(
                  divisions: divisions,
                  min: min,
                  max: max,
                  value: snapshot.data ?? value,
                  onChanged: onChanged,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }


Step 24:   

In Flutter registerPlugins is a method that is used to register custom plugins. Plugins provide a way to integrate platform-specific functionalities into your Flutter app. These functionalities are usually not available through the Flutter framework itself. Developers can create their own custom plugins or use existing plugins from the Flutter community to access features.


  void registerPlugins(Registrar registrar) {
    AudioServiceWeb.registerWith(registrar);
    AudioSessionWeb.registerWith(registrar);
    JustAudioPlugin.registerWith(registrar);
    registrar.registerMessageHandler();
  }

Step 25:   

Run the project using the flutter run command:


    flutter run


👉   Demo



Comments

  1. Please develop more apps like this and share it with us.
    Thanks

    ReplyDelete

Post a Comment