ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
### 1.背景    音乐播放页面实现的功能有 :    (1)当前歌曲的信息    (2)歌词显示    (3)进度条显示当前进度    (4)倒计时    (5)返回 和(下载或分享)    (6)当前音乐的控制 :播放/暂停/下一曲/下一曲    如下图所示 :                                                             ![](https://box.kancloud.cn/2016-04-19_5715764cb5718.jpg)      这篇将实现整个界面的布局; ### 2.布局实现    (1)整个模糊背景实现      整个布局,设置了一张背景图片;    (2)当前歌曲信息                                                               ![](https://box.kancloud.cn/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://box.kancloud.cn/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://box.kancloud.cn/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://box.kancloud.cn/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://box.kancloud.cn/2016-04-19_5715764d83595.jpg) ### 5.总结 播放页面的实现,与MusciSerivce 通信密切,同时还有Notification ,比如说 音乐暂停,播放页面暂停后,通知栏上也要暂停;若控制通知栏上播放,那么播放页面既要同步歌曲信息,也要保持进度进度一致性,时间一致性和状态一致性。