返回

Flutter 实战:从零开始构建网易云音乐 APP(五、播放功能逻辑)

前端

前言

大家好,欢迎来到 Flutter 实战系列的第五篇。在本系列中,我们将从零开始构建一个网易云音乐 APP。在上一篇中,我们已经完成了音乐播放器的基本界面设计。在本篇中,我们将重点介绍播放歌曲和播放歌曲一系列的逻辑。

实现播放逻辑

首先,我们需要导入必要的库。

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

接下来,我们需要创建一个新的类来管理播放逻辑。

class MusicPlayer extends StatefulWidget {
  const MusicPlayer({Key? key}) : super(key: key);

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

class _MusicPlayerState extends State<MusicPlayer> {
  // 播放器对象
  late Luanpotter luanpotter;

  // 当前播放的歌曲索引
  int currentIndex = 0;

  // 歌曲列表
  List<Song> songs = [];

  // 是否正在播放
  bool isPlaying = false;

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

    // 初始化播放器
    luanpotter = Luanpotter();

    // 初始化歌曲列表
    songs = [
      Song(
        title: 'Despacito',
        artist: 'Luis Fonsi, Daddy Yankee',
        url: 'https://luanpotter.com/music/despacito.mp3',
      ),
      Song(
        title: 'Shape of You',
        artist: 'Ed Sheeran',
        url: 'https://luanpotter.com/music/shape_of_you.mp3',
      ),
      Song(
        title: 'Perfect',
        artist: 'Ed Sheeran',
        url: 'https://luanpotter.com/music/perfect.mp3',
      ),
    ];

    // 监听播放器事件
    luanpotter.onPlayerEvent.listen((event) {
      switch (event) {
        case PlayerEvent.started:
          setState(() {
            isPlaying = true;
          });
          break;
        case PlayerEvent.paused:
          setState(() {
            isPlaying = false;
          });
          break;
        case PlayerEvent.stopped:
          setState(() {
            isPlaying = false;
          });
          break;
        case PlayerEvent.completed:
          // 播放下一首歌曲
          nextSong();
          break;
      }
    });
  }

  @override
  void dispose() {
    // 释放播放器资源
    luanpotter.dispose();

    super.dispose();
  }

  // 播放歌曲
  void playSong(Song song) {
    luanpotter.play(song.url);

    setState(() {
      currentIndex = songs.indexOf(song);
      isPlaying = true;
    });
  }

  // 暂停歌曲
  void pauseSong() {
    luanpotter.pause();

    setState(() {
      isPlaying = false;
    });
  }

  // 停止歌曲
  void stopSong() {
    luanpotter.stop();

    setState(() {
      isPlaying = false;
    });
  }

  // 下一首歌曲
  void nextSong() {
    if (currentIndex < songs.length - 1) {
      currentIndex++;
      playSong(songs[currentIndex]);
    }
  }

  // 上一首歌曲
  void previousSong() {
    if (currentIndex > 0) {
      currentIndex--;
      playSong(songs[currentIndex]);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 歌曲封面
        Image.network(songs[currentIndex].coverUrl),

        // 歌曲标题和歌手
        Text(
          '${songs[currentIndex].title} - ${songs[currentIndex].artist}',
          style: TextStyle(fontSize: 20),
        ),

        // 播放进度条
        Slider(
          value: luanpotter.position.inMilliseconds.toDouble(),
          min: 0,
          max: luanpotter.duration.inMilliseconds.toDouble(),
          onChanged: (value) {
            luanpotter.seekTo(Duration(milliseconds: value.toInt()));
          },
        ),

        // 播放控制按钮
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            IconButton(
              icon: Icon(Icons.skip_previous),
              onPressed: previousSong,
            ),
            IconButton(
              icon: isPlaying ? Icon(Icons.pause) : Icon(Icons.play_arrow),
              onPressed: isPlaying ? pauseSong : playSong,
            ),
            IconButton(
              icon: Icon(Icons.skip_next),
              onPressed: nextSong,
            ),
          ],
        ),
      ],
    );
  }
}

接下来,我们需要在 APP 的主界面中使用这个播放器。

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

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

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('网易云音乐'),
      ),
      body: Column(
        children: [
          // 歌曲列表
          Expanded(
            child: ListView.builder(
              itemCount: songs.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text('${songs[index].title} - ${songs[index].artist}'),
                  onTap: () {
                    playSong(songs[index]);
                  },
                );
              },
            ),
          ),

          // 音乐播放器
          MusicPlayer(),
        ],
      ),
    );
  }
}

运行程序

现在,我们可以运行程序并测试播放功能。

flutter run

如果一切顺利,你应该可以看到一个音乐播放器界面。你可以点击歌曲列表中的歌曲来播放歌曲。你也可以使用播放控制按钮来控制歌曲的播放。

结语

在本篇中,我们介绍了如何使用 Flutter 从零开始构建网易云音乐 APP 的播放功能逻辑。我们使用 luanpotter Flutter 包来构建音乐播放器,并实现了播放、暂停、快进、快退、调节音量、切换歌曲等功能。