扣丁音乐(六)——PlayUIActivity(播放页面)
本文出自:http://blog.csdn.net/dt235201314/article/details/51360013
代码上传到github,欢迎start:https://github.com/JinBoy23520/TingTingMusic
一丶音乐播放页实现功能
1.音乐格信息显示,大图显示
2.播放功能,上一曲,下一曲,暂停
3.音乐进度显示
4.切换播放模式
二丶显示效果
三丶原理及代码实现
1.自定义接口回调的方法实现UI状态切换(进度位置,播放那一首歌)
2.seekbar实现歌曲进度同步及监听
3.service统一实现Activity,Fragment的播放功能及UI图片统一
4.BaseActivity基类统一实现服务绑定,音乐播放状态,直接调用MusicPlayService
代码实现
activity_play_ui.xml
xml version="1.0" encoding="utf-8"?>PlayUIActivity.javaxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/skin2"> android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/relativeLayout"> android:layout_centerVertical="true" android:id="@+id/iv_pull_down" android:layout_width="wrap_content" android:layout_height="20dp" android:src="@drawable/backtrack" android:layout_marginLeft="10dp"/> android:id="@+id/ll_play_ui_top" android:gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginTop="5dp" android:layout_toRightOf="@+id/iv_pull_down" android:layout_toLeftOf="@+id/iv_share"> android:id="@+id/tv_play_ui_song" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="听妈妈的话" android:textColor="@color/white" android:textSize="18sp"/> android:id="@+id/tv_play_ui_artist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#c1c1c1" android:paddingTop="5dp" android:text="周杰伦"/> android:id="@+id/iv_share" android:layout_width="wrap_content" android:layout_height="25dp" android:src="@drawable/share" android:layout_marginRight="10dp" android:layout_alignParentRight="true" android:layout_centerVertical="true"/> android:layout_alignParentBottom="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:id="@+id/linearLayout"> android:layout_width="match_parent" android:layout_height="wrap_content"> android:id="@+id/tv_play_ui_play_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:textColor="@color/white"/> android:id="@+id/sb_play_ui_seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:thumb="@drawable/seekbar_cycle" android:layout_toRightOf="@+id/tv_play_ui_play_time" android:layout_toLeftOf="@+id/tv_play_ui_end_time"/> android:id="@+id/tv_play_ui_end_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" android:layout_centerVertical="true" android:textColor="@color/white" android:layout_marginRight="10dp" android:layout_alignParentRight="true"/> android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_marginTop="20dp" android:orientation="horizontal"> android:id="@+id/iv_play_ui_play_mode" android:layout_width="wrap_content" android:layout_height="30dp" android:src="@drawable/list_cycle" android:layout_weight="1"/> android:id="@+id/iv_play_ui_previous" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/previous" android:layout_weight="1"/> android:id="@+id/iv_play_ui_play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/play" android:layout_weight="1"/> android:id="@+id/iv_play_ui_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/next" android:layout_weight="1"/> android:id="@+id/iv_play_ui_menu" android:layout_width="wrap_content" android:layout_height="35dp" android:src="@drawable/menu" android:layout_weight="1"/> android:layout_marginLeft="70dp" android:layout_marginRight="70dp" android:layout_marginTop="20dp" android:layout_marginBottom="10dp" android:layout_width="match_parent" android:layout_height="wrap_content"> android:id="@+id/iv_play_ui_like" android:layout_width="wrap_content" android:layout_height="25dp" android:layout_weight="1" android:src="@drawable/like"/> android:id="@+id/iv_play_ui_download" android:layout_width="wrap_content" android:layout_height="25dp" android:layout_weight="1" android:src="@drawable/download"/> android:id="@+id/iv_play_ui_add" android:layout_width="wrap_content" android:layout_height="28dp" android:layout_weight="1" android:src="@drawable/add"/> android:layout_width="match_parent" android:layout_height="250dp" android:background="#00FFFFFF" android:id="@+id/iv_ablum2" android:layout_below="@+id/relativeLayout" android:layout_marginTop="25dp" />
public class PlayUIActivity extends BaseActivity implements View.OnClickListener{private ImageView iv_pull_down,iv_play_ui_play,iv_play_ui_next,iv_play_ui_previous,iv_play_ui_play_mode,iv_ablum2; private TextView tv_play_ui_song,tv_play_ui_artist,tv_play_ui_end_time,tv_play_ui_play_time; private ArrayListBaseActivity.javamp3Infos; private SeekBar sb_play_ui_seekbar; private static final int UPDATE_TIME = 0x1; private static MyHandler myHandler; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_play_ui); iv_pull_down = (ImageView)findViewById(R.id.iv_pull_down); iv_ablum2 = (ImageView)findViewById(R.id.iv_ablum2); tv_play_ui_song = (TextView)findViewById(R.id.tv_play_ui_song); tv_play_ui_artist = (TextView)findViewById(R.id.tv_play_ui_artist); tv_play_ui_end_time = (TextView)findViewById(R.id.tv_play_ui_end_time); tv_play_ui_play_time = (TextView)findViewById(R.id.tv_play_ui_play_time); iv_play_ui_play = (ImageView)findViewById(R.id.iv_play_ui_play); iv_play_ui_next = (ImageView)findViewById(R.id.iv_play_ui_next); iv_play_ui_previous = (ImageView)findViewById(R.id.iv_play_ui_previous); iv_play_ui_play_mode = (ImageView)findViewById(R.id.iv_play_ui_play_mode); sb_play_ui_seekbar = (SeekBar)findViewById(R.id.sb_play_ui_seekbar); iv_pull_down.setOnClickListener(this); iv_play_ui_play.setOnClickListener(this); iv_play_ui_next.setOnClickListener(this); iv_play_ui_previous.setOnClickListener(this); iv_play_ui_play_mode.setOnClickListener(this); mp3Infos = MediaUtils.getMp3Infos(this); myHandler = new MyHandler(this); }@Override protected void onDestroy() {super.onDestroy(); }@Override protected void onResume() {super.onResume(); bindMusicPlayService(); }@Override protected void onPause() {super.onPause(); unbindMusicPlayService(); }/** * 进度条控件已经内部处理过了,开始时间的改变是在子线程中改变主线程的UI,这当然是不可以的 * 怎么办呢,用你最熟悉的Handler处理吧 */ static class MyHandler extends android.os.Handler{//内部类去要想使用外部类的权限,就得把外部类拿进来 private PlayUIActivity playUIActivity; public MyHandler(PlayUIActivity playUIActivity){this.playUIActivity = playUIActivity; }@Override public void handleMessage(Message msg) {super.handleMessage(msg); if(playUIActivity!=null){switch (msg.what){case UPDATE_TIME:playUIActivity.tv_play_ui_play_time.setText(MediaUtils.formatTime(msg.arg1)); break; }}}}//这里是子线程,不断的发送msg给主线程,通知其更改UI @Override public void publish(int progress) {Message msg = myHandler.obtainMessage(UPDATE_TIME); msg.arg1 = progress; try {Thread.sleep(500); } catch (InterruptedException e) {e.printStackTrace(); }myHandler.sendMessage(msg); sb_play_ui_seekbar.setProgress(progress); }@Override public void change(int position) {Mp3Info mp3Info = mp3Infos.get(position); tv_play_ui_song.setText(mp3Info.getTitle()); tv_play_ui_artist.setText(mp3Info.getArtist()); tv_play_ui_end_time.setText(MediaUtils.formatTime(mp3Info.getDuration())); iv_play_ui_play.setImageResource(R.drawable.pause); //获取专辑封面图片 Bitmap albumBitmap = MediaUtils.getArtwork(this, mp3Info.getId(), mp3Info.getAlbumId(), true, false); //改变播放界面专辑封面图片 iv_ablum2.setImageBitmap(albumBitmap); sb_play_ui_seekbar.setProgress(0); sb_play_ui_seekbar.setMax((int)mp3Info.getDuration()); if(musicPlayService.isPlaying()){iv_play_ui_play.setImageResource(R.drawable.pause); }else {iv_play_ui_play.setImageResource(R.drawable.play); }switch (musicPlayService.getPlay_mode()){case MusicPlayService.ORDER_PLAY:iv_play_ui_play_mode.setImageResource(R.drawable.list_cycle); //iv_play_ui_play_mode.setTag(MusicPlayService.ORDER_PLAY); break; case MusicPlayService.RANDOM_PLAY:iv_play_ui_play_mode.setImageResource(R.drawable.random); //iv_play_ui_play_mode.setTag(MusicPlayService.RANDOM_PLAY); break; case MusicPlayService.SINGLE_PLAY:iv_play_ui_play_mode.setImageResource(R.drawable.single_cycle); //iv_play_ui_play_mode.setTag(MusicPlayService.SINGLE_PLAY); break; default:break; }}@Override public void onClick(View view) {switch (view.getId()){case R.id.iv_pull_down:finish(); overridePendingTransition(R.anim.abc_fade_in, R.anim.abc_fade_out); break; case R.id.iv_play_ui_play:if(musicPlayService.isPlaying()){musicPlayService.pause(); iv_play_ui_play.setImageResource(R.drawable.play); }else{if(musicPlayService.isPause()){musicPlayService.start(); iv_play_ui_play.setImageResource(R.drawable.pause); }else{musicPlayService.play(0); }}break; case R.id.iv_play_ui_previous:musicPlayService.previous(); break; case R.id.iv_play_ui_next:musicPlayService.next(); break; case R.id.iv_play_ui_play_mode:switch (musicPlayService.getPlay_mode()){case MusicPlayService.ORDER_PLAY:iv_play_ui_play_mode.setImageResource(R.drawable.random); musicPlayService.setPlay_mode(MusicPlayService.RANDOM_PLAY); break; case MusicPlayService.RANDOM_PLAY:iv_play_ui_play_mode.setImageResource(R.drawable.single_cycle); musicPlayService.setPlay_mode(MusicPlayService.SINGLE_PLAY); break; case MusicPlayService.SINGLE_PLAY:iv_play_ui_play_mode.setImageResource(R.drawable.list_cycle); musicPlayService.setPlay_mode(MusicPlayService.ORDER_PLAY); }break; default:break; }} }
/** * 自定义基础activity,用来让其他activity继承,作为工具activity,用于绑定服务 */ public abstract class BaseActivity extends FragmentActivity {protected MusicPlayService musicPlayService; private boolean isBound = false; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); }private ServiceConnection conn = new ServiceConnection() {@Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) {MusicPlayService.PlayBinder playBinder = (MusicPlayService.PlayBinder)iBinder; musicPlayService = playBinder.getMusicPlayService(); musicPlayService.setMusicUpdateListener(musicUpdateListener); //绑定成功后调用监听onChange方法 musicUpdateListener.onChange(musicPlayService.getCurrentPosition()); }@Override public void onServiceDisconnected(ComponentName componentName) {musicPlayService = null; isBound = false; }}; private MusicPlayService.MusicUpdateListener musicUpdateListener = new MusicPlayService.MusicUpdateListener(){@Override public void onPublish(int progress) {publish(progress); }@Override public void onChange(int position) {change(position); }}; public abstract void publish(int progress); public abstract void change(int position); //绑定服务 public void bindMusicPlayService(){if(!isBound){Intent intent = new Intent(this,MusicPlayService.class); bindService(intent,conn,BIND_AUTO_CREATE); isBound = true; }}//解除绑定服务 public void unbindMusicPlayService(){if(isBound){unbindService(conn); isBound = false; }} }MusicPlayService.java
/** * 实现功能: * 1、点击列表上的某首歌播放 * 2、点击播放按钮,从暂停转为播放状态 * 3、点击暂停按钮,从播放状态转为暂停状态 * 4、上一首 * 5、下一首 * 6、播放进度显示 * 7、播放模式 */ public class MusicPlayService extends Service implements MediaPlayer.OnCompletionListener,MediaPlayer.OnErrorListener{private MediaPlayer mediaPlayer; private ArrayListmp3Infos; private int currentPosition;//列表当前位置 private MusicUpdateListener musicUpdateListener;//设置属性 private boolean isPause = false; //顺序播放、单曲循环、随机播放 public static final int ORDER_PLAY = 1; public static final int RANDOM_PLAY = 2; public static final int SINGLE_PLAY = 3; public int play_mode = ORDER_PLAY; //用于设置或者获得播放模式 public int getPlay_mode() {return play_mode; }public void setPlay_mode(int play_mode) {this.play_mode = play_mode; }//在fragment或者activity中轻松获得状态 public boolean isPause(){return isPause; }//开启线程池 private ExecutorService es = Executors.newSingleThreadExecutor(); Runnable updateStatusRunnable = new Runnable() {@Override public void run() {while (true){if(musicUpdateListener!=null&&mediaPlayer!=null&&mediaPlayer.isPlaying()){musicUpdateListener.onPublish(getCurrentProgress()); }}}}; public MusicPlayService() {}Random random = new Random(); //用于监听当前歌曲播放完后,下一首该如何播放 @Override public void onCompletion(MediaPlayer mediaPlayer) {switch (play_mode){case ORDER_PLAY:next(); break; case RANDOM_PLAY:play(random.nextInt(mp3Infos.size())); break; case SINGLE_PLAY:play(currentPosition); break; default:break; }}@Override public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {mediaPlayer.reset(); return false; }class PlayBinder extends Binder{public MusicPlayService getMusicPlayService(){return MusicPlayService.this; }}@Override public void onCreate() {super.onCreate(); mediaPlayer = new MediaPlayer(); mp3Infos = MediaUtils.getMp3Infos(this); mediaPlayer.setOnCompletionListener(this); mediaPlayer.setOnErrorListener(this); //在进入每一个绑定service时,就监听进度改变事件,而状态改变监听则是在启动播放的时候 es.execute(updateStatusRunnable); }//启动线程就得销毁 @Override public void onDestroy() {super.onDestroy(); if(es!=null && es.isTerminated()){es.shutdown(); es = null; }}@Nullable @Override public IBinder onBind(Intent intent) {return new PlayBinder(); }//点击列表上的某首歌播放 public void play(int position){if(position>=0 && position<mp3Infos.size()){Mp3Info mp3Info = mp3Infos.get(position); try {mediaPlayer.reset(); mediaPlayer.setDataSource(this, Uri.parse(mp3Info.getUrl())); mediaPlayer.prepare(); mediaPlayer.start(); currentPosition = position; }catch (IOException e){e.printStackTrace(); }if(musicUpdateListener!=null){musicUpdateListener.onChange(currentPosition); }}}//点击播放按钮,从暂停转为播放状态 public void start(){if(mediaPlayer!=null && !mediaPlayer.isPlaying()){mediaPlayer.start(); }}//点击暂停按钮,从播放状态转为暂停状态 public void pause(){if(mediaPlayer.isPlaying()){mediaPlayer.pause(); isPause = true; }}//下一首 public void next(){if(currentPosition >= mp3Infos.size()-1){currentPosition = 0; }else{currentPosition++; }play(currentPosition); }//上一首 public void previous(){if(currentPosition<=0){currentPosition = mp3Infos.size()-1; }else{currentPosition--; }play(currentPosition); }//更新状态的接口 public interface MusicUpdateListener{public void onPublish(int progress); public void onChange(int position); }public void setMusicUpdateListener(MusicUpdateListener musicUpdateListener) {this.musicUpdateListener = musicUpdateListener; }//在音乐播放中,获得播放的位置信息 public int getDuration(){return mediaPlayer.getDuration(); }//跳转到某个地方 public void seekTo(int msec){mediaPlayer.seekTo(msec); }//返回当前的位置 public int getCurrentPosition(){return currentPosition; }//获得当前位置 public int getCurrentProgress(){if(mediaPlayer!=null && mediaPlayer.isPlaying()){return mediaPlayer.getCurrentPosition(); }return 0; }//反馈状态 public boolean isPlaying(){if(mediaPlayer!=null&&mediaPlayer.isPlaying()){return mediaPlayer.isPlaying(); }return false; }}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
