继续学习Android,使用监听和消息处理来实现一个简单的视频进度条。
一、效果预览
二、布局
使用VideoView播放视频,在VideoView底部添加播放进度条,进度条左右分别显示当前播放时间和视频总时间。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<VideoView
android:id="@+id/video"
android:layout_width="match_parent"
android:layout_height="100pt"
android:keepScreenOn="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignBottom="@+id/video">
<TextView
android:id="@+id/leftTime"
android:layout_width="0dp"
android:layout_height="match_parent"
android:textColor="#B1AFAF"
android:layout_weight="2"/>
<SeekBar
android:id="@+id/seekbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="8"/>
<TextView
android:id="@+id/rightTime"
android:layout_width="0dp"
android:layout_height="match_parent"
android:textColor="#B1AFAF"
android:layout_weight="2"/>
</LinearLayout>
</RelativeLayout>
三、实现
VideoView可以通过getDuration方法获取视频总长度,调用seekbar.setMax将视频长度与进度条长度同步;设置了总长度后,我们还需要在改变当前进度条进度时,同时改变视频的播放进度,SeekBar可以设置一个监听器,我们需要在进度改变时执行相应的操作。
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
handler.removeMessages(1);
if(b) {
videoView.seekTo(i);
}
Message message = Message.obtain();
message.arg1 = videoView.getDuration();
message.arg2 = videoView.getCurrentPosition();
message.what=1;
//handler.sendMessageDelayed(message,100);
handler.sendMessage(message);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
这里使用发送消息来同步时间,各个组件的监听中只需要负责发送需要改变的时间和总时间,消息处理中会执行我们定义的方法来更改对应的UI。
四、全部代码
makeTimeString():实现了对总时间的格式转换,用于显示当前播放时间和总时间。
public class VideoActivity extends AppCompatActivity {
private VideoView videoView;
private SeekBar seekBar;
private TextView leftTime;
private TextView rightTime;
@SuppressLint("HandlerLeak")
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
int allLength = msg.arg1;
int currentPosition = msg.arg2;
leftTime.setText(makeTimeString(currentPosition));
rightTime.setText(makeTimeString(allLength));
seekBar.setProgress(currentPosition);
msg = Message.obtain();
msg.arg1 = videoView.getDuration();
msg.arg2 = videoView.getCurrentPosition();
msg.what = 1;
if(videoView.isPlaying()){
handler.sendMessageDelayed(msg,100);
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
seekBar=findViewById(R.id.seekbar);
leftTime=findViewById(R.id.leftTime);
rightTime=findViewById(R.id.rightTime);
videoView=findViewById(R.id.video);
//String videoPath = "https:vfx.mtime.cn/Video/2019/07/12/mp4/190712140656051701.mp4";
//videoView.setVideoPath(videoPath);
Uri uri = Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.video);
videoView.setVideoURI(uri);
videoView.start();
videoView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(videoView.isPlaying())
videoView.pause();
else {
handler.removeMessages(1);
videoView.start();
Message message = Message.obtain();
message.arg1 = videoView.getDuration();
message.arg2 = videoView.getCurrentPosition();
message.what=1;
handler.sendMessageDelayed(message,100);
}
}
});
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
seekBar.setMax(videoView.getDuration());
Message message = Message.obtain();
message.arg1 = videoView.getDuration();
message.arg2 = videoView.getCurrentPosition();
message.what=1;
handler.sendMessageDelayed(message,100);
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
handler.removeMessages(1);
if(b) {
videoView.seekTo(i);
}
Message message = Message.obtain();
message.arg1 = videoView.getDuration();
message.arg2 = videoView.getCurrentPosition();
message.what=1;
//handler.sendMessageDelayed(message,100);
handler.sendMessage(message);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
//时间转换成字符串,用于显示当前播放时间和总时间
private String makeTimeString(int secs) {
String durationFormat = "%1$02d:%2$02d:%3$02d";
StringBuilder sFormatBuilder = new StringBuilder();
Formatter sFormatter = new Formatter(sFormatBuilder, Locale.getDefault());
sFormatBuilder.setLength(0);
secs = secs / 1000;
Object[] timeArgs = new Object[3];
timeArgs[0] = secs / 3600;
timeArgs[1] = (secs % 3600) / 60;
timeArgs[2] = (secs % 3600 % 60) % 60;
return sFormatter.format(durationFormat,timeArgs).toString().trim();
}
}