先说原理:音乐播放需要使用到Service,而播放栏也是属于音乐播放的,那么为什么我们不把这两者合在一起呢?
把UI和音乐Service合在一起,用Service来控制UI界面不是更简单。在进入Activity的时候判定是否播放列表不为空或者是否正在播放音乐来动态添加UI界面。简单的这样就实现了播放栏的常驻(虽然只是看起来,但是挺简单的,完成后效果也不错)。
实现:
1.建立MusicService类,继承自Service基类,并且实现基本的音乐播放逻辑,这里我实现了添加播放列表以及播放的方法。我预想的网易云音乐的播放面板存在逻辑为,只要播放列表不为空以及列表内存在可播放音乐,就存在这个音乐播放控制面板。这里为了简单,我们就先只检查播放列表是否为空,不为空就实例化出来播放控制面板。为空的话就去掉。这里我Activity发消息给Service是通过绑定开启服务的方式,具体实现不再赘述,直接说添加播放列表方法:
在Service中定义添加播放列表方法,如果是只添加一首,那么就播放这一首,添加多首就不改变当前的播放状态:
/**
* 添加音乐到播放列表,添加一首
*/
private void addPlayListInner(Mp3Info mp3s){
if(!PlayList.contains(mp3s))
{
//不存在这首歌曲,直接存入
//播放这首歌返回
Help.INSERT_VALUES_TO_SQLITE(PlayListContentProvider.CONTENT_SONGS_URI,mp3s);//存入数据库保存
PlayList.add(mp3s);
CurrentPlayPosition = PlayList.size()-1;//赋值当前播放位置为现在的位置
}
//播放当前音乐
playInner(CurrentPlayPosition);
}
下面再来看播放方法(只是一个基础例子,需要完善的还有很多):
/**
* 实现方法
*
* @param position 播放位置
*
* @return
*/
private boolean playInner(int position){
try {
playPreInner(position);
mediaPlayer.start();
isPlaying = true;
CreateFloatView();
setPlayBarValue(PlayList.get(CurrentPlayPosition),mediaPlayer);//设置播放栏
//使用定时器提交播放进度
Timer timer = new Timer();
TimerTask task = new TimerTask(){
@Override
public void run(){
musicProcessBar.setProgress(mediaPlayer.getCurrentPosition());
}
};
timer.schedule(task,0,1000);
}
catch(Exception e)
{
e.printStackTrace();
}
return true;
}
可以看到,上面播放音乐的方法中我们调用了一个方法,是CreateFloatView()--这是用来创建播放控制面板的,实现如下:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<!--浮动音乐控制布局-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:id="@+id/float_Music_Container"
android:orientation="vertical"
android:background="@color/colorHalfTransparentWrite">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/colorHalfTransparentWrite">
<!--音乐图片-->
<ImageView
android:id="@+id/float_MusicImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toEndOf="@+id/float_MusicImage"
android:layout_marginLeft="5dp">
<TextView
android:id="@+id/float_Music_Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:textColor="#000000"/>
<TextView
android:id="@+id/float_Music_Artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorPrimarySliver"
android:textSize="14dp"
android:layout_marginTop="3dp"/>
</LinearLayout>
<!--右边的控制按钮-->
<RelativeLayout
android:layout_width="180dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true">
<!--播放列表按钮-->
<ImageView
android:id="@+id/float_Play_List"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:src="@drawable/playbar_btn_playlist"/>
<!--播放或者暂停按钮-->
<ImageView
android:id="@+id/float_Play_Btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/playbar_play_btn"/>
<!--下一曲音乐-->
<ImageView
android:id="@+id/float_Next_Music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:src="@drawable/playbar_play_next_btn"/>
</RelativeLayout>
</RelativeLayout>
<!--音乐进度-->
<ProgressBar
android:id="@+id/float_Music_ProgressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="0"
android:visibility="visible"
style="@style/ProgressBar_Mini"/>
</LinearLayout>
实现方法:
/**
* 建立底部浮动栏的方法
*/
public void CreateFloatView(){
if(PlayList.size() > 0) {
mFloatView = LayoutInflater.from(getBaseContext()).inflate(R.layout.float_music_control_layout,null);
ViewGroup mDecorView = (ViewGroup)StaticValue.NowActivity.getWindow().getDecorView();
mContentContainer = (FrameLayout)((ViewGroup)mDecorView.getChildAt(0)).getChildAt(1);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
musicProcessBar = (ProgressBar)mFloatView.findViewById(R.id.float_Music_ProgressBar);
musicImageView = (ImageView)mFloatView.findViewById(R.id.float_MusicImage);
musicNameTextView = (TextView)mFloatView.findViewById(R.id.float_Music_Name);
musicArtistTextView = (TextView)mFloatView.findViewById(R.id.float_Music_Artist);
musicPlayBtn = (ImageView)mFloatView.findViewById(R.id.float_Play_Btn);
musicNextBtn = (ImageView)mFloatView.findViewById(R.id.float_Next_Music);
musicPlayListBtn = (ImageView)mFloatView.findViewById(R.id.float_Play_List);
mFloatView.findViewById(R.id.float_Music_Container).setOnClickListener(this);
musicPlayBtn.setOnClickListener(this);
musicPlayListBtn.setOnClickListener(this);
musicNextBtn.setOnClickListener(this);
//获取当前正在播放的音乐
layoutParams.gravity = Gravity.BOTTOM;//设置对齐位置
mContentContainer.addView(mFloatView,layoutParams);
if(! mediaPlayer.isPlaying()) {
//没有正在播放的,准备当前位置的音乐,设置值
playPreInner(- 1);
}
setPlayBarValue(PlayList.get(CurrentPlayPosition),mediaPlayer);//设置播放控制面板的值
}
}
/**
* 设置播放栏的值
* @param NowMp3 正在播放的mp3对象
* @param mediaPlayer1 当前的mediaPlayer对象
*/
private void setPlayBarValue(Mp3Info NowMp3,MediaPlayer mediaPlayer1)
{
musicProcessBar.setMax(mediaPlayer1.getDuration());//设置播放进度进度条最大值,
musicProcessBar.setProgress(mediaPlayer1.getCurrentPosition());//设置播放进度条当前进度值
musicNameTextView.setText(NowMp3.getDisplayName());//设置音乐名称
musicImageView.setImageResource(R.drawable.ic_menu_gallery);//设置音乐专辑图片
musicArtistTextView.setText(NowMp3.getArtist());//设置歌手名称
//设置为暂停的图片
musicPlayBtn.setImageResource(R.mipmap.playbar_btn_pause);
}
我们接着在服务的onCreate方法中调用CreateFloatView()方法以便打开应用的时候检测是否添加播放栏,还有
重点::::
在onResume()方法中也调用CreateFloatView()方法,这样才能让已经被挂起的Activity重新进入前台时能够检查是否添加播放栏!
在onResume()方法中也调用CreateFloatView()方法,这样才能让已经被挂起的Activity重新进入前台时能够检查是否添加播放栏!
在onResume()方法中也调用CreateFloatView()方法,这样才能让已经被挂起的Activity重新进入前台时能够检查是否添加播放栏!
事重三!
,下面看看效果:
由于这种效果使用静态图片不好观看,动态图还没弄好软件,我看再搞搞,先忍受这个东西吧:
程序进入:
点击音乐栏目:
点击本地音乐:
点击扫描:
扫描完成:
回到音乐界面:
点击一首歌曲播放,播放面板就显示出来了!:
现在我们返回主界面看看是否有播放面板:
播放面板已经有了,说明我们的逻辑是对的,看起来效果也还不错。
需要源码的我已经上传到了我的CSDN 下载地址:http://download.csdn.net/detail/qq_21265915/9661736
最后,如有错误欢迎指正