实现音频的播放效果及音频列表播放踩坑,效果图:
WX20180130-103857.png

实现:
1.声明
private TextView tv_time_start = null;//播放的时间进度
private MediaPlayer player = null;
private ImageView iv_go_left = null;//快退
private ImageView iv_go_right = null;//快进
private ImageView iv_start = null;//开始播放按钮
private ImageView iv_pause = null;//暂停播放按钮
private SeekBar skbProgress = null;// 播放进度条
private volatile boolean isDrag = false; //互斥量,seekbar拖动或者Timer
private Thread thread = null;
private String sourse = "";//音乐路径
private boolean isPause = false;//是否暂停
private int tag = -1;//音频列表,点击播放时判断是否为同一Item
解决在音频列表里播放时,因为不同item的点击出现播放紊乱的情况,将播放按钮与position进行绑定,在点击时根据position来区分下一步操作是该暂停还是该下一个item的播放:
Object object = iv_start.getTag();
int tag = -1;
if (null != object) {
tag = Integer.valueOf(object + "");
if (this.tag != tag && this.tag != -1) {
completion();//恢复初始状态
}
}
this.tag = tag;
2.播放或者继续播放
/**
* 播放or继续播放
* */
public void start() {
iv_start.setVisibility(View.INVISIBLE);
iv_pause.setVisibility(View.VISIBLE);
if (true == isPause) {
player.start();//继续播放
isPause = false;
setProgress();
} else
play();//开始播放音乐
}
3.播放音频
/**
* 播放音频
* */
private void play() {
try {
if (null == player) {
player = new MediaPlayer();
}
player.reset();
player.setDataSource(sourse);
player.prepare();
player.start();//开始播放
isPause = false;
setProgress();
} catch (IllegalArgumentException e) {
} catch (SecurityException e) {
} catch (IllegalStateException e) {
} catch (NullPointerException e) {
} catch (IOException e) {
e.printStackTrace();
}
}
4.暂停播放
/**
* 暂停播放
* 这里的非空判断,是为了解决列表播放时,滑动的复用导致的NullPointerException异常
* */
public void pause() {
if (null != iv_start)
iv_start.setVisibility(View.VISIBLE);
if (null != iv_pause)
iv_pause.setVisibility(View.INVISIBLE);
try {
if (null != player && player.isPlaying() && !isPause) {
player.pause();//暂停播放
isPause = true;
}
} catch (IllegalStateException e) {
}
}
5.进度条设置
private void setProgress() {
try {
skbProgress.setMax(player.getDuration());
skbProgress.setOnSeekBarChangeListener(new SeekbarmusicEvent());
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer arg0) {
// TODO Auto-generated method stub
completion();
}
});
} catch (IllegalArgumentException e) {
} catch (SecurityException e) {
} catch (IllegalStateException e) {
} catch (NullPointerException e) {
}
try {
thread = new Thread(new SeekBarThread());
thread.start();
} catch (
IllegalStateException e) {
}
}
处理拖动seekbar事件
//处理拖动seekbarmusic事件
class SeekbarmusicEvent implements SeekBar.OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
tv_time_start.setText(showTime(seekBar.getProgress()));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
isDrag = true;//拖动seekbar停止timer
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
try {
tv_time_start.setText(showTime(seekBar.getProgress()));
player.seekTo(skbProgress.getProgress());
isDrag = false;//开启timer
thread = new Thread(new SeekBarThread()); // 启动线程
thread.start();
if (skbProgress.getProgress() == skbProgress.getMax()) {
iv_pause.setVisibility(View.VISIBLE);
iv_start.setVisibility(View.INVISIBLE);
tv_time_start.setText("00:00");
player.seekTo(0);
skbProgress.setProgress(0);
isPause = false;
}
} catch (IllegalStateException e) {
}
}
}
class SeekBarThread implements Runnable {
@Override
public void run() {
try {
while (null != player && ! isDrag && player.isPlaying()) {
skbProgress.setProgress(player.getCurrentPosition());
Thread.sleep(100);
}
} catch (InterruptedException e) {
} catch (IllegalStateException e) {
}
}
}
/**
* 根据进度格式化时间
* */
public static String showTime(Object time) {
SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
formatter.setTimeZone(TimeZone.getTimeZone("00:00"));
String hms = formatter.format(time);
return hms;
}
6.快进/快退
/**
* 快进
* */
public void forWard() {
try {
Log.i("sxh", "forWard");
if (player != null && player.isPlaying()) {
int position = player.getCurrentPosition();
player.seekTo(position + 5000);
}
} catch (IllegalStateException e) {
}
}
/**
* 快退
* */
public void backWard() {
try {
if (player != null && player.isPlaying()) {
int position = player.getCurrentPosition();
if (position > 5000) {
position -= 5000;
} else {
position = 0;
}
player.seekTo(position);
}
} catch (IllegalStateException e) {
}
}
7.播放完成后的恢复默认状态
/**
* 播放完成
* 这里的非空判断是为了避免音频列表播放时,因为item的复用导致的异常
* */
public void completion() {
try {
if (null != iv_start)
iv_start.setVisibility(View.VISIBLE);
if (null != iv_pause)
iv_pause.setVisibility(View.INVISIBLE);
if (null != tv_time_start)
tv_time_start.setText("00:00");
if (null != skbProgress)
skbProgress.setProgress(0);
isPause = false;
if (null != player)
player.seekTo(0);
} catch (IllegalStateException e) {
}
}
8.停止播放与销毁
/**
* 销毁
* */
public void destoryPlayer() {
if (null != player) {
player.release();
isPause = false;
}
}
/***
* 停止播放
* */
public void stop(){
if (null != player)
player.stop();
}
列表播放需要注意:
- 列表滑动时,要停止当前正在播放的item里的音频,并把各个状态恢复初始状态,否则滑动后由于item的复用会导致播放状态混乱
view_recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (null != adapter)
adapter.audioCompletion(); //上方封装的completion()和stop()方法
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
- 音频列表,当前item处于被操作状态的同时去操作下一个item时,要及时将当前状态恢复为初始状态,否则会出现异常,处理方法:将播放按钮与position进行绑定,在播放时判断前后点击的position是否相同,相同的话就根据状态判断是暂停还是继续播放,如果不相同就停止播放并将状态恢复成默认情况。
((ViewHolderAudio) holder).iv_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String audio = mList.get(position).getVideo();
holder.iv_play.setTag(position);
mAudioTools.setSource(holder.tv_time_start, holder.sk_bar, holder.iv_play,holder.iv_pause, audio);
mAudioTools.start();
}
});
//工具类里初始化view方法里
public void setSource(...){
Object object = iv_start.getTag();
int tag = -1;
if (null != object) {
tag = Integer.valueOf(object + "");
if (this.tag != tag && this.tag != -1) {
completion();
}
}
this.tag = tag;
}
- 当Activity 处于onPause()和onDestroy()状态时,要及时停止播放或者销毁
@Override
public void onDestroy() {
super.onDestroy();
destoryPlayer();
}
@Override
public void onPause() {
super.onPause();
pause();
}
网友评论