Flutter Functions

 

Building a Music Player App with Flutter: UI and Audio Playback

In today’s fast-paced world, music is an essential part of our lives. With the rise of mobile apps, music streaming has become more convenient than ever. Have you ever wondered how those music player apps are created? If you’re interested in app development and want to dive into the world of music streaming, you’re in the right place. In this tutorial, we’ll walk you through the process of building a music player app using Flutter, a popular UI framework developed by Google. We’ll cover both the UI design and audio playback aspects, so let’s get started!

Building a Music Player App with Flutter: UI and Audio Playback

1. Setting Up Your Flutter Project

Before we dive into the app’s design and functionality, make sure you have Flutter installed on your system. If not, you can follow the official installation guide on the Flutter website. Once you have Flutter up and running, create a new Flutter project using the following command:

bash
flutter create music_player_app

Navigate to your project directory:

bash
cd music_player_app

You’re all set to start building your music player app!

2. Designing the Music Player UI

A visually appealing user interface is crucial for any app’s success. Let’s design the UI of our music player app step by step.

2.1. Creating the App Layout

In Flutter, the UI is built using widgets. Open the lib/main.dart file and replace the default code with the following:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Music Player App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MusicPlayerScreen(),
    );
  }
}

class MusicPlayerScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Music Player'),
      ),
      body: Center(
        child: Text('Welcome to the Music Player App!'),
      ),
    );
  }
}

In this code, we’ve created the basic structure of our app with a title bar and a centered text widget. Now, let’s move on to designing the play screen.

2.2. Designing the Play Screen

The play screen will display album art, song details, and playback controls. Update the MusicPlayerScreen class as follows:

dart
class MusicPlayerScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Music Player'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Image.asset('assets/album_art.jpg'),
          SizedBox(height: 20),
          Text(
            'Song Title',
            style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
          ),
          Text('Artist Name'),
          SizedBox(height: 20),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              IconButton(
                icon: Icon(Icons.skip_previous),
                onPressed: () {},
              ),
              IconButton(
                icon: Icon(Icons.play_arrow),
                onPressed: () {},
              ),
              IconButton(
                icon: Icon(Icons.skip_next),
                onPressed: () {},
              ),
            ],
          ),
        ],
      ),
    );
  }
}

In this code snippet, we’ve added placeholders for album art, song title, artist name, and playback controls. The Image.asset widget loads the album art from the assets folder.

2.3. Implementing the Playlist

To implement the playlist, we’ll create a separate screen that displays a list of songs. Add the following code to your main.dart:

dart
class PlaylistScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Playlist'),
      ),
      body: ListView.builder(
        itemCount: songs.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(songs[index].title),
            subtitle: Text(songs[index].artist),
            onTap: () {
              // Navigate to the Play Screen with the selected song
            },
          );
        },
      ),
    );
  }
}

Here, we’ve used a ListView.builder to display the list of songs. Each song is represented by a ListTile widget with its title and artist. You can replace songs with a list of song objects.

3. Integrating Audio Playback

Now that we have our UI in place, let’s move on to integrating audio playback functionality into our app.

3.1. Adding Audio Files to Your Project

Start by adding your audio files to the assets folder of your project. Make sure to update your pubspec.yaml file to include the audio files:

yaml
flutter:
  assets:
    - assets/album_art.jpg
    - assets/song1.mp3
    - assets/song2.mp3
    # Add more audio files as needed

3.2. Setting Up Audio Playback Functionality

Flutter provides the audioplayers package for handling audio playback. Add this package to your pubspec.yaml file:

yaml
dependencies:
  flutter:
    sdk: flutter
  audioplayers: ^latest_version

Replace latest_version with the actual version of the package.

In your MusicPlayerScreen class, import the necessary libraries and set up the audio player:

dart
import 'package:audioplayers/audioplayers.dart';

class MusicPlayerScreen extends StatelessWidget {
  final AudioPlayer audioPlayer = AudioPlayer();

  // ... Rest of the code ...

  @override
  Widget build(BuildContext context) {
    // ... Rest of the build method ...

    IconButton(
      icon: Icon(Icons.play_arrow),
      onPressed: () {
        audioPlayer.play('assets/song1.mp3');
      },
    ),

    // ... Rest of the build method ...
  }
}

In this example, when the play button is pressed, the audio player will start playing the specified audio file.

3.3. Play, Pause, and Seek Controls

To add play, pause, and seek controls, modify your MusicPlayerScreen class as follows:

dart
class MusicPlayerScreen extends StatefulWidget {
  @override
  _MusicPlayerScreenState createState() => _MusicPlayerScreenState();
}

class _MusicPlayerScreenState extends State<MusicPlayerScreen> {
  final AudioPlayer audioPlayer = AudioPlayer();
  bool isPlaying = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Music Player'),
      ),
      body: Column(
        // ... Rest of the UI code ...

        IconButton(
          icon: Icon(isPlaying ? Icons.pause : Icons.play_arrow),
          onPressed: () {
            if (isPlaying) {
              audioPlayer.pause();
            } else {
              audioPlayer.play('assets/song1.mp3');
            }
            setState(() {
              isPlaying = !isPlaying;
            });
          },
        ),

        // ... Rest of the UI code ...
      ),
    );
  }
}

Here, we’ve added a bool isPlaying variable to keep track of the playback state. The play button’s icon changes based on whether the audio is playing or paused.

4. Enhancing the User Experience

To create a polished music player app, let’s implement additional features that enhance the user experience.

4.1. Displaying Song Progress

Show the progress of the currently playing song using a progress indicator. Update your MusicPlayerScreen class:

dart
class _MusicPlayerScreenState extends State<MusicPlayerScreen> {
  final AudioPlayer audioPlayer = AudioPlayer();
  bool isPlaying = false;
  double progress = 0.0;

  @override
  void initState() {
    super.initState();
    audioPlayer.onAudioPositionChanged.listen((Duration newPosition) {
      setState(() {
        progress = newPosition.inMilliseconds.toDouble();
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    // ... Rest of the build method ...

    Slider(
      value: progress,
      onChanged: (value) {
        audioPlayer.seek(Duration(milliseconds: value.toInt()));
      },
      min: 0.0,
      max: audioPlayer.duration.inMilliseconds.toDouble(),
    ),

    // ... Rest of the build method ...
  }
}

In this code, the onAudioPositionChanged event listener updates the progress variable as the song plays. The Slider widget allows users to seek to a specific position in the song.

4.2. Implementing Shuffle and Repeat Functionality

Add shuffle and repeat buttons to your MusicPlayerScreen class:

dart
class _MusicPlayerScreenState extends State<MusicPlayerScreen> {
  final AudioPlayer audioPlayer = AudioPlayer();
  bool isPlaying = false;
  bool isShuffling = false;
  bool isRepeating = false;

  // ... Rest of the code ...

  Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      IconButton(
        icon: Icon(Icons.shuffle, color: isShuffling ? Colors.blue : null),
        onPressed: () {
          setState(() {
            isShuffling = !isShuffling;
          });
        },
      ),
      IconButton(
        icon: Icon(Icons.skip_previous),
        onPressed: () {},
      ),
      IconButton(
        icon: Icon(Icons.play_arrow),
        onPressed: () {
          // ... Rest of the play button logic ...
        },
      ),
      IconButton(
        icon: Icon(Icons.skip_next),
        onPressed: () {},
      ),
      IconButton(
        icon: Icon(Icons.repeat, color: isRepeating ? Colors.blue : null),
        onPressed: () {
          setState(() {
            isRepeating = !isRepeating;
          });
        },
      ),
    ],
  ),

  // ... Rest of the code ...
}

The shuffle and repeat buttons change color based on their respective states. When shuffled, the app randomly selects the next song to play.

4.3. Handling Background Audio Playback

To allow audio playback even when the app is in the background, you need to implement background audio handling. Update your main.dart:

dart
void main() {
  runApp(MyApp());
  audioPlayer.startHeadlessService();
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // ... Rest of the code ...
    );
  }
}

Adding audioPlayer.startHeadlessService() ensures that audio playback continues even if the app is minimized.

Conclusion

Congratulations! You’ve successfully built a music player app using Flutter, integrating a beautiful UI design and audio playback functionality. From creating a stunning play screen to handling audio playback and enhancing the user experience, you’ve covered the key aspects of building a music player app. This tutorial provides a solid foundation for further customization and feature expansion. Whether you’re a beginner or an experienced developer, Flutter opens the doors to crafting engaging and interactive apps that resonate with users’ interests and passions. Happy coding!

Previously at
Flag Argentina
Brazil
time icon
GMT-3
Full Stack Systems Analyst with a strong focus on Flutter development. Over 5 years of expertise in Flutter, creating mobile applications with a user-centric approach.