音乐播放器的实现(四)—— 歌曲列表、顺序播放、单曲循环、随机播放、自动下一曲

传送门:(完整工程见第五章篇尾)
音乐播放器的实现(一)—— Audio Listener和Audio Source面板的介绍
音乐播放器的实现(二)—— UI面板的制作
音乐播放器的实现(三)—— 进度条控制、播放、暂停、上(下)一曲、播放时间和总时间显示
音乐播放器的实现(五)—— 音量的加减和静音
前言:
上一篇简单的实现了算是顺序播放的上一曲和下一曲,这篇加上播放模式(顺序播放、单曲循环、随机播放),再优化上/下一曲,同时显示所有歌曲的列表,并能点击播放对应的歌曲音频。

先看下最终效果:

具体操作
一、首先,我们还是先完善UI面板:
1、在上一篇的基础上,新建一个按钮Button命名为pModeImage,Button的图片用来显示播放模式对应的图片(文本可以删掉);
2、准备三张图片放入Project面板中的Resources文件夹下的Sprite文件夹中(可根据自己需求放置,但一定要在Resources文件夹下,当然后台代码对应的路径也要更改),分别命名为:stright、circle和random;
3、新建一个Scroll View,用来显示歌曲的列表,在content下新建一个Button,用来点击播放对应歌曲。在content上添加布局组件,调整相关参数,使Button大小位置合适,最后把该Button拖至Project面板中形成一个预制体,存放在Prefab文件夹中,再删掉或隐藏掉content下的Button按钮。
最终效果如下图所示:

二、核心代码
1、相对上一篇,我把播放音频的方法独立了出来,方便调用。

 /// <summary>/// 播放索引为index的音频/// </summary>/// <param name="index">音频索引</param>void playMusic(int index){aus.clip = auc[index];          //音频播放器的音频为aus数组中索引对应的音频slid.value = 0;                 //初始化进度条aus.time = 0;                   //初始化音乐的播放时间(从头开始播)aus.Play();                     //播放音频}

2、音乐列表
实例化每个音频按钮,形成音乐列表,该方法在Start()中调用,即开始运行时就形成歌曲列表。(其中
item为上面制作的Button预制体。)

     public GameObject item;         //要实例化的列表按钮对象,即Button预制体private GameObject it;          //实例化出的列表音频按钮void initItem()//音频列表{List<GameObject> L = new List<GameObject>();//列表Lfor (int i = 0; i < auc.Length; i++){it = Instantiate(item);                 //实例化音频列表的各个按钮//设置父节点为Scroll View下的contentit.transform.SetParent(GameObject.Find("Content").transform, false);//音频名string[] name = auc[i].name.Split('-');//连接音频名,序号、名字、作者it.transform.Find("Text").GetComponent<Text>().text = string.Format("<size=18>{0}  {1}--</size>" + "<size=18>{2}</size>", i + 1, name[0], name[1]);//把每个按钮放入列表LL.Add(it);}GameObject[] g = new GameObject[L.Count];   //数组g,长度等于列表L 的长度L.CopyTo(g);                                //把列表L的内容复制到数组g中//给每个音频按钮加上监听,点击即播放对应音频foreach(GameObject gob in g){gob.GetComponent<Button>().onClick.AddListener(delegate{index = Array.IndexOf(g, gob);      //获取当前点击的按钮在数组g中的索引playMusic(index);                   //播放音频});}}

效果如下图所示:

3、播放模式
(1)枚举出顺序播放、单曲循环、随机播放这三个模式:

     public enum playMode{stright,//列表循环circle1,//单曲循环random  //随机播放}private playMode playM = playMode.stright;          //初始是顺序播放private GameObject pModeImage;                      //播放模式的图片切换

在Start()中调用:

 void initPlayMode()//初始化播放模式{//找到名为pModeImage的按钮pModeImage = GameObject.Find("pModeImage");//给它添加监听(调用PlayMode方法,来切换播放模式)pModeImage.GetComponent<Button>().onClick.AddListener(PlayMode);}

以下为PlayMode()方法:

 //变量t,初始值为1int t = 1;/// <summary>/// 播放模式/// </summary>public void PlayMode(){t++;if (t == 1){//播放模式为顺序播放playM = playMode.stright;//上传顺序播放对应的图片pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/stright");}if(t==2){//播放模式为单曲循环playM = playMode.circle1;//上传单曲循环对应的图片pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/circle");}if(t==3){//播放模式为随机播放playM = playMode.random;//上传速记播放对应的图片pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/random");//初始化tt = 0;}}

(2)重新修改了LastMusic()和NextMusic()方法:
上一曲:

 private void LastMusic(){if (playM == playMode.random)   //如果播放模式是随机播放randomRange();              //随机播放else{index--;                        //索引减一//若索引等于-1,即当前播放的音频是aus数组列表的第一首,则上一首应为aus数组列表的最后一首if (index == -1)index = auc.Length - 1;playMusic(index);}}

下一曲:

private void NextMusic(){if(playM==playMode.random)      //如果播放模式是随机播放randomRange();              //随机播放else{index++;                        //索引加一//若索引等于aus音频数组的长度,即当前播放的音频是最后一首,则下一首应为aus数组列表的第一首if (index == auc.Length)index = 0;playMusic(index);//播放音频}}

随机播放时调用的代码:

 public  void  randomRange()//随机播放{int r = UnityEngine.Random.Range(0, auc.Length);//生成随机数(包含0,不包含auc.Length);if(index == r)                                      //如果随机数等于当前播放的音频的索引(避免播放同一首)r++;                                        //索引加一//若索引等于aus音频数组的长度,即当前播放的音频是最后一首,则下一首应为aus数组列表的第一首if (r == auc.Length)r = 0;playMusic(r);//播放音频}

4、自动播放下一曲
当进度条走到最后时,播放下一曲,若是单曲循环,则依旧播放当前的音频

 void Slider()//当进度条走到最后时,播放下一曲{if (currentHour == clipHour && currentMinute == clipMinute && currentSecond == clipSecond){if (playM == playMode.circle1)//如果播放模式是单曲循环,下一曲还是当前这首playMusic(index);elseNextMusic();//下一曲}}

完整版代码:

DragSlider脚本不变。 Player脚本如下:

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Player: MonoBehaviour {public enum playMode{stright,//列表循环circle1,//单曲循环random  //随机播放}public Text musicName;          //显示歌曲的名字及歌手public Text nowTime;            //显示歌曲已播放的时间长度public Text allTime;            //显示当前歌曲的总时间长度public Slider slid;             //进度条public Transform buttons;       //按钮所在的集合体public AudioClip[] auc;         //存放歌曲的数组public AudioSource aus;         //音频播放器private int index;              //数组aus的索引private int currentHour, currentMinute, currentSecond;          //已播放的时间(时、分、秒)private int clipHour, clipMinute, clipSecond;                   //总时间(时、分、秒)private playMode playM=playMode.stright;                        //初始是顺序播放private GameObject pModeImage;                                  //播放模式的图片切换private GameObject vioce_butt, voice_text, voice_slid;          //音量按钮、音量数字、音量进度条int clickNum=0,value;//变量bool mouseIn;//鼠标进入public GameObject item;         //要实例化的列表按钮对象private GameObject it;          //实例化出的列表音频按钮public static Player _instance;void initItem()//音频列表{List<GameObject> L = new List<GameObject>();//列表Lfor (int i = 0; i < auc.Length; i++){it = Instantiate(item);                 //实例化音频列表的各个按钮it.transform.SetParent(GameObject.Find("Content").transform, false);//音频名string[] name = auc[i].name.Split('-');//连接音频名,序号、名字、作者it.transform.Find("Text").GetComponent<Text>().text = string.Format("<size=18>{0}  {1}--</size>" + "<size=18>{2}</size>", i + 1, name[0], name[1]);//把每个按钮放入列表LL.Add(it);}GameObject[] g = new GameObject[L.Count];   //数组g,长度等于列表L 的长度L.CopyTo(g);                                //把列表L的内容复制到数组g中//给每个音频按钮加上监听,点击即播放对应音频foreach(GameObject gob in g){gob.GetComponent<Button>().onClick.AddListener(delegate{index = Array.IndexOf(g, gob);playMusic(index);                   //播放音频});}}void initVoice()//初始化{vioce_butt = GameObject.Find("voice_button");voice_text = GameObject.Find("voice_text");voice_slid = GameObject.Find("voice_slider");//voice_slid.SetActive(false);                 //开始时声音进度条不显示(当鼠标放在音量按钮上时显示)voice_slid.GetComponent<Slider>().value = 20;//开始声音为20;//开始先调用一次,设置初始的音量大小voice();//给进度条添加监听,进度条的值改变即调用voice()方法voice_slid.GetComponent<Slider>().onValueChanged.AddListener(delegate { voice(); });//给声音按钮添加监听vioce_butt.GetComponent<Button>().onClick.AddListener(delegate{clickNum++;//点击按钮的次数if(clickNum==1)//1为打开静音,0为关闭静音{//打开音频播放器的静音aus.mute = true;//上传对应的静音的图片vioce_butt.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/voiceMute");//存下点击静音时的进度条的值value = (int)voice_slid.GetComponent<Slider>().value;//进度条的value值为0voice_slid.GetComponent<Slider>().value = 0;}else{//关闭音频播放器的静音aus.mute = false;//上传对应的不静音的图片vioce_butt.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/voice1");//进度条的值变为关闭静音前的值voice_slid.GetComponent<Slider>().value = value;//初始化点击次数clickNum = 0;}});}void initPlayMode()//初始化播放模式{//找到名为pModeImage的按钮pModeImage = GameObject.Find("pModeImage");//给它添加监听(调用PlayMode方法,来切换播放模式)pModeImage.GetComponent<Button>().onClick.AddListener(PlayMode);}void Start(){_instance = this;aus.Stop();                                                 //开始运行时不播放,点播放键才开始播放#region 注:该方式虽然可以直接达到拖动进度条就播放到进度条当前的音乐,但会产生滋滋啦啦的杂音,是因为进度条value变化,使之不断调用onValueChanged,从而让音乐的进度发生了变化,音乐前后颠倒,不断重叠////// 所以新建了个DragSlider脚本,挂在进度条上,来实现拖动播放的效果/////slid.onValueChanged.AddListener(delegate//{//    //加上之后,避免拖动进度条到最后不松手时报错//    if (slid.value == 1)//        return;//    //给进度条添加事件监听,每当拖动进度条,歌曲从相应的位置播放//    aus.time = slid.value * aus.clip.length;//});#endregionforeach (Transform go in buttons)                           //遍历所有的操作按钮{go.GetComponent<Button>().onClick.AddListener(delegate  //根据按钮名给按钮添加事件监听{switch (go.name){case "lastM":       //点击“上一曲”按钮LastMusic();break;case "pause":       //点击“暂停”按钮Pause();break;case "play":        //点击“播放”按钮Play();break;case "nextM":       //点击“下一曲”按钮NextMusic();break;}});}initItem();                                                 //音频列表initVoice();                                                //音量部分初始化initPlayMode();                                             //初始化播放模式}void Update () {//当前播放过的时间nowtime();//当前正在播放的音频的总时间alltime();//当前正在播放的音乐nowMusic();//单机左键,隐藏所有要隐藏的//setActiveFalse();}void nowtime()//当前播放过的时间{currentHour = (int)aus.time / 3600; //时currentMinute = (int)(aus.time - currentHour * 3600) / 60;//分currentSecond = (int)(aus.time - currentHour * 3600 - currentMinute * 60);//秒//显示当前播放过的时间nowTime.text = string.Format("{0:D2}:{1:D2}:{2:D2} ",currentHour, currentMinute, currentSecond);//进度条变化//(之后更新版)如果当前没有拖拽进度条if(!DragSlider.isDrag)slid.value = aus.time / aus.clip.length;}/// <summary>/// 歌曲总时间/// </summary>void alltime(){//slid.value = 0;clipHour = (int)aus.clip.length / 3600;//时clipMinute = (int)(aus.clip.length - clipHour * 3600) / 60;//分clipSecond = (int)(aus.clip.length - clipHour * 3600 - clipMinute * 60);//秒//显示歌曲总时间allTime.text = string.Format("{0:D2}:{1:D2}:{2:D2}",clipHour, clipMinute, clipSecond);}/// <summary>/// 上一曲/// </summary>private void LastMusic(){if (playM == playMode.random)   //如果播放模式是随机播放randomRange();              //随机播放else{index--;                        //索引减一//若索引等于-1,即当前播放的音频是aus数组列表的第一首,则上一首应为aus数组列表的最后一首if (index == -1)index = auc.Length - 1;playMusic(index);}}private void Pause()                //暂停{aus.Pause();}private void Play()                 //播放{//如果当前正在播放,则返回if (aus.isPlaying)return;aus.Play();}/// <summary>/// 下一曲/// </summary>public void NextMusic(){if(playM==playMode.random)      //如果播放模式是随机播放randomRange();              //随机播放else{index++;                        //索引加一//若索引等于aus音频数组的长度,即当前播放的音频是最后一首,则下一首应为aus数组列表的第一首if (index == auc.Length)index = 0;playMusic(index);//播放音频}} void nowMusic()                     //当前的音频{AudioClip clip = aus.clip;      //当前播放的音频string n = aus.clip.name;       //当前播放的音频的名字string[] na = n.Split('-');     //以“-”为分割点,把音频名分为若干部分//显示当前正在播放的歌曲的名字【歌曲名(默认字体,25号)+歌手名(默认字体,18号,红色)的形式】musicName.text = string.Format("<size=25>{0}</size>" + "\n<size=18><color=#FF0000FF>{1}</color></size>", na[0], na[1]);index = Array.IndexOf(auc, clip);//当前播放的音频在aus数组中的索引Slider();                        //当进度条走到最后时,播放下一曲}void Slider()//当进度条走到最后时,播放下一曲{if (currentHour == clipHour && currentMinute == clipMinute && currentSecond == clipSecond){if (playM == playMode.circle1)//如果播放模式是单曲循环,下一曲还是当前这首playMusic(index);elseNextMusic();//下一曲}}/// <summary>/// 播放索引为index的音频/// </summary>/// <param name="index">音频索引</param>void playMusic(int index){aus.clip = auc[index];          //音频播放器的音频为aus数组中索引对应的音频slid.value = 0;                 //初始化进度条aus.time = 0;                   //初始化音乐的播放时间(从头开始播)aus.Play();                     //播放音频}//变量tint t = 1;/// <summary>/// 播放模式/// </summary>public void PlayMode(){t++;if (t == 1){//播放模式为顺序播放playM = playMode.stright;//上传顺序播放对应的图片pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/stright");}if(t==2){//播放模式为单曲循环playM = playMode.circle1;//上传单曲循环对应的图片pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/circle");}if(t==3){//播放模式为随机播放playM = playMode.random;//上传速记播放对应的图片pModeImage.GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprite/random");//初始化tt = 0;}}//设置和显示音量大小void voice(){//把进度条最大值改为100,最小值为0//音频播放器的音量volume = 进度条的值 * 0.01f。(因为volume的范围为:0~1)aus.volume = voice_slid.GetComponent<Slider>().value * 0.01f;//音量的文本显示(为进度条的value值,value值是浮点型,这里显示成整型)voice_text.GetComponent<Text>().text = ((int)voice_slid.GetComponent<Slider>().value).ToString();}public  void voice_button(bool on){if(on){voice_slid.SetActive(true);mouseIn = true;}else{mouseIn = false;voice_slid.SetActive(false);} }/// <summary>/// 单机左键,隐藏所有要隐藏的/// </summary>void setActiveFalse(){if(Input.GetMouseButtonDown(0)){if(mouseIn==false)voice_slid.SetActive(false);}}public  void  randomRange()//随机播放{int r = UnityEngine.Random.Range(0, auc.Length);//生成随机数(包含0,不包含auc.Length);if(index == r)                                      //如果随机数等于当前播放的音频的索引(避免播放同一首)r++;                                        //索引加一//若索引等于aus音频数组的长度,即当前播放的音频是最后一首,则下一首应为aus数组列表的第一首if (r == auc.Length)r = 0;playMusic(r);//播放音频}}

代码备注的也比较详细,若文中存在错误或者描述不清的地方也请指正,欢迎评论区留言共同探讨,以上。

音乐播放器的实现(四)—— 歌曲列表、顺序播放、单曲循环、随机播放、自动下一曲相关推荐

  1. android音乐播放器开发 SweetMusicPlayer 载入歌曲列表

    上一篇写了播放器的总体实现思路,http://blog.csdn.net/huweigoodboy/article/details/39855653,如今来总结下载入歌曲列表. 代码地址:https: ...

  2. 原生H5+JS+CSS实现音乐播放器(上下一首,随机单曲循环播放,进度条,播放列表)

    学了前端小半个月了,今天自己动手写一个音乐播放器实现的功能有 播放列表 ,随机单曲循环播放,上下一首,暂停和开始,静音,音量增加减少,进度条(收藏功能暂未实现,为了排版好看添加的,后续补充收藏等功能) ...

  3. 苹果播放器实现单曲循环

    一直觉得苹果的音乐播放器比较坑. 但是,用了qq音乐播放器,发现,我竟然没法把电脑里的音乐导入到手机里.更坑. 必须重用苹果的音乐播放器.下简称MP(music player). 因为学英语,必须要单 ...

  4. Android开发本地及网络Mp3音乐播放器(十七)已存在歌曲歌词下载

    转载请注明出处: http://blog.csdn.net/iwanghang/article/details/51388896 觉得博文有用,请点赞,请留言,请关注,谢谢!~ 实现功能: 已存在歌曲 ...

  5. 微信小程序——实现音乐播放器(上下切换歌曲、进度条拉动、暂停与继续播放)

    小伙伴们你们有没有想过自己搞一个播放器,播上自己喜欢的歌单,那是多么的惬意啊~ 之前,小编遇到一个项目,语音导览的播放器.其实跟播放歌单一个道理. 但是一看微信开发文档里面的音频API又是那么多,我们 ...

  6. 怎么精炼java代码_网页播放器开发(四)代码精炼提纯(示例代码)

    四.精简提炼 我们的播放器基本实现了,但是代码复用不高,所以我们要进行封装,以插件的形式体现. 1.插件的基本运行代码如下: ;(function(undefined){'use strict'; . ...

  7. 简单音乐播放器html+css+基础vue+含源码,有搜索和播放mv功能,代码可直接复制用。

    题目:html+css+基础vue实现的简单音乐播放器(含源码),有搜索和播放mv功能,代码可直接复制用. 问题描述: 如果vue刚入门,掌握一些基础语法后就可以写一个简单的音乐播放器来练练手~~如果 ...

  8. android音乐播放器 单曲循环,[Android] MediaPlayer单曲循环不卡顿

    [TOC] 0x00 需求 单曲循环播放歌曲,要求过度连贯,听不出来卡顿感觉. 0x01 解决思路 MediaPlayer 对于常见的音乐播放,我们第一时间想到的应该就是它,它有一个方法 MediaP ...

  9. 【小河今学 | JavaScript + JQuery】音乐播放器4-音量调整、单曲循环、全部循环

    08.18今天来完善音乐播放器的音量调整.单曲循环和全部循环功能. 本篇基于上一篇[小河今学 | JavaScript + JQuery]音乐播放器3-歌词轮播和进度条跳转功能实现 一.音量调整 首先 ...

最新文章

  1. Tomcat V6 Examples移植到Apusic V5.1
  2. 我把面试官问的没话说了,这样好吗?
  3. 用 Flask 来写个轻博客 (18) — 使用工厂模式来生成应用对象
  4. 轻松搞懂sscanf和sprintf
  5. python输入整数_Python中实现输入一个整数的案例
  6. Grafana分析Nginx日志
  7. codeforces 356C Bear and Square Grid
  8. arduinoesp8266定时器_ESP8266深度睡眠与Arduino IDE(NodeMCU)
  9. ZOJ 1057 Undercut(简单模拟)
  10. 算法讲解 -- 二分图之 匈牙利算法
  11. c语言输出后面空格,新人提问:如何将输出时每行最后一个空格删除
  12. Gradle发布4.7版本,支持Java 10
  13. PyTorch 1.0 中文文档:torch.Storage
  14. C语言程序设计期末卷子,C语言程序设计试题1
  15. 宿舍电源额定500w,我的电脑550w的,有什么办法能解决吗?
  16. 【BZOJ1880】[Sdoi2009]Elaxia的路线(最短路)
  17. 写一个函数,首先要明确是完成一个流程,还是一个功能
  18. xp自带打印驱动相关
  19. deepin安装NVIDIA显卡驱动
  20. 毫米和像素怎么换算_像素和厘米怎么换算?

热门文章

  1. 多人配音怎么制作的?给你推荐几个有声小说多人配音软件
  2. a标签download属性下载excel
  3. SitePoint Podcast#182:John Allsopp的网络指导
  4. Flutter-绘制小猪佩奇
  5. 3D次世代MAYA游戏角色建模的方法
  6. Java毕业设计_高校学生考勤管理系统设计与实现
  7. Phoenix 数据导入与导出
  8. EHR中关于参加工作日期(社会工龄起算日)计算法定年假的一点思考
  9. 释放被占用的COM口,实测有效
  10. MFC程序解析以及使用cl.exe、link.exe编译连接Windows API和MFC程序