Android实战 – 音心播放器 (MusicActivity-音乐播放页面界面实现)
最后更新于:2022-04-01 10:52:49
### 1.背景
音乐播放页面实现的功能有 :
(1)当前歌曲的信息
(2)歌词显示
(3)进度条显示当前进度
(4)倒计时
(5)返回 和(下载或分享)
(6)当前音乐的控制 :播放/暂停/下一曲/下一曲
如下图所示 :
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764cb5718.jpg)
这篇将实现整个界面的布局;
### 2.布局实现
(1)整个模糊背景实现
整个布局,设置了一张背景图片;
(2)当前歌曲信息
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764d3b818.jpg)
最主要的是它的背景颜色,在color.xml 中配置 颜色为 :其中55表示透明度,半透明状态实现;
~~~
<color name="app_color_whrit">#55FCFCFC</color>
~~~
总布局为RelativeLayout :
~~~
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="80dp"
android:layout_marginTop="10dp"
android:background="@color/app_color_whrit" >
<ImageView
android:id="@+id/iv_music_songpic"
android:layout_width="80dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:scaleType="fitXY"
android:src="@drawable/moren_big" />
<TextView
android:id="@+id/tv_music_songname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="18dp"
android:layout_toRightOf="@+id/iv_music_songpic"
android:maxLines="2"
android:text="@string/list_item_song_name"
android:textColor="@color/text_color_black"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_music_singer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="10dp"
android:layout_marginRight="20dp"
android:text="@string/list_item_singer_name"
android:textColor="@color/app_color_zi"
android:textSize="12sp" />
</RelativeLayout>
~~~
(3)歌词的实现是自定义View
在这里不分享歌词的自定义View ,歌词的显示 在后面将要实现,因为内容稍微有点多。
~~~
<cn.labelnet.ui.LrcView
android:id="@+id/lrc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:padding="5dp"
android:text="@string/music_song_ci"
lrc:animationDuration="1000"
lrc:currentTextColor="?attr/currentTextColor"
lrc:dividerHeight="24dp"
lrc:normalTextColor="@android:color/white"
lrc:textSize="16sp" />
~~~
(4)控制实现
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764d4ba5a.jpg)
基本控制的实现,图标在这里就不分享了,自己可以在网上找到。
~~~
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="80dp"
android:layout_marginTop="10dp"
android:padding="10dp" >
<ImageView
android:id="@+id/music_play"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:src="@drawable/pause" />
<ImageView
android:id="@+id/music_next"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@+id/music_play"
android:src="@drawable/next" />
<ImageView
android:id="@+id/music_prev"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:layout_marginRight="20dp"
android:layout_toLeftOf="@+id/music_play"
android:src="@drawable/prevers" />
</RelativeLayout>
~~~
(5)进度条/倒计时实现
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764d5c417.jpg)
倒计时和进度条实现,因为要同步歌曲的进度,所以内容也将单独的写一篇文章,敬请期待;
~~~
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="80dp"
android:layout_marginTop="10dp"
android:background="@color/app_color_whrit" >
<ProgressBar
android:id="@+id/progressbar_music"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_time_sheng"
android:layout_centerInParent="true"
android:max="100"
android:progress="50" />
<TextView
android:id="@+id/tv_time_sheng"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="@string/procress_1_23"
android:textColor="@color/app_color_zi" />
<TextView
android:id="@+id/tv_time_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="10dp"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="@string/procress_1_23"
android:textColor="@color/app_color_zi" />
</RelativeLayout>
~~~
### 3.歌曲信息适配实现
这里使用了广播(BoradCastReceiver )来实现,上面几篇中已经使用了,当MusicActivity启动的时候,发送广播到MusicService ,MusicService收到后,发送广播给MusicActivity ,进行初始化界面。这就是为什么前面进行开始就启动MusicService了吧。
基本过程图解 :
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764d6bb04.jpg)
(1)初始化基本过程如上图所示,初始化流程。
(2)有一个问题,在第一篇中不是说了,音乐专辑中没有提供图片,所以我们需要自己动手去搜索里获得图片链接,在去请求图片;
### 4.SDK网络请求封装与图解
(1)首先实现NetRequest 接口,所有的showAPI SDK请求都来自它
~~~
public interface NetRequest {
/**
* 网络请求接口
*/
//请求字符串
String requestStringData();
void requestStringData(int topid);
void requestStringData(String keyword);
void requestStringLrcData(String songId);
}
~~~
(2)NetRequestImp中实现接口NetRequest ,但不写方法内容,提供空方法
~~~
public class NetRequestImp implements NetRequest {
/**
* 实现NetRequest接口,给想要实现方法的提供想要的方法
*
*/
@Override
public String requestStringData() {
return null;
}
@Override
public void requestStringData(int topid) {
// 这里给MusicRequest 提供此方法,在MusicRequest 中 重写这个方法即可
}
@Override
public void requestStringData(String keyword) {
}
@Override
public void requestStringLrcData(String songId) {
}
}
~~~
(3)实现MusicRequest类 继承自 NetRequestImp , 重写使用的方法, 实现里面的方法
~~~
/**
* 音乐请求工具类 ShowAPi 提供的方法
*
*/
public class MusicRequest extends NetRequestImp {
/**
* 音乐列表信息
*/
private final String HOT_MUSIC_URL = "http://route.showapi.com/213-4";
private final String SHOW_API_APPID = "xxxxx";
private final String SHOW_API_SECRET = "xxxxx";
/**
* 音乐id , 查询信息
*/
private final String SELECT_SONG_BY_KEYWORD_URL="http://route.showapi.com/213-1";
/**
* 歌词地址
*/
private final String GET_SONG_LRC_URL="http://route.showapi.com/213-2";
ShowApiRequest apiRequest = null;
// 提供异步回调方法
private AsyncHttpResponseHandler musicAsyncHandler;
public void setMusicAsyncHandler(AsyncHttpResponseHandler handler) {
this.musicAsyncHandler = handler;
}
/**
* 热门榜 : 数据请求
*/
@Override
public void requestStringData(int topid) {
new ShowApiRequest(HOT_MUSIC_URL, SHOW_API_APPID, SHOW_API_SECRET)
.setResponseHandler(musicAsyncHandler)
.addTextPara("topid", topid + "").post();
}
/**
* 关键字搜索
*/
@Override
public void requestStringData(String keyword) {
new ShowApiRequest(SELECT_SONG_BY_KEYWORD_URL, SHOW_API_APPID, SHOW_API_SECRET)
.setResponseHandler(musicAsyncHandler)
.addTextPara("keyword", keyword)
.addTextPara("page", "1")
.post();
}
/**
* 获取歌词
*/
@Override
public void requestStringLrcData(String songId) {
new ShowApiRequest(GET_SONG_LRC_URL ,SHOW_API_APPID,SHOW_API_SECRET)
.setResponseHandler(musicAsyncHandler)
.addTextPara("musicid",songId+"")
.post();
}
}
~~~
(4)需要实现AsyncHandler ,单独的实现该类,后使用回调函数,将值回调出来;
~~~
public class MusicAsyncHandler extends AsyncHttpResponseHandler {
private MusicAsync mAsync;
private List<MusicModel> mms = null;
public void setMAsync(MusicAsync mAsync) {
this.mAsync = mAsync;
mms = new ArrayList<MusicModel>();
}
@Override
public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {
// 失败
mAsync.onFail(arg3.getMessage() + " : " );
}
@Override
public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
// 成功
String msg = "no msg";
if (arg2.length > 0) {
msg = new String(arg2);
mms = StringUtil.getMusicList(msg);
if(mms!=null){
mAsync.onSuccess(mms);
}else{
msg="解析为null";
mAsync.onFail(msg);
}
} else {
mAsync.onFail(msg);
}
}
}
~~~
(5)回调接口 函数
~~~
public interface MusicAsync {
//成功
void onSuccess(List<MusicModel> mms);
//失败
void onFail(String msg);
}
~~~
(6)图解
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-19_5715764d83595.jpg)
### 5.总结
播放页面的实现,与MusciSerivce 通信密切,同时还有Notification ,比如说 音乐暂停,播放页面暂停后,通知栏上也要暂停;若控制通知栏上播放,那么播放页面既要同步歌曲信息,也要保持进度进度一致性,时间一致性和状态一致性。