模仿原生的提供的视频播放器VideoView,封装一个仿微信的视频播放器。
原生的VideoView,为了解耦和方便定制,把MediaPlayer的播放逻辑和UI界面展示及操作相关的逻辑分离。
加入边播放边缓存的功能,引入AndroidVideoCache缓存库。
微信的播放界面如下:
界面的设计封装
通过FrameLayout 叠上两层 UI Layout + TextureView。
/**
* 创建FrameLayout容器
*/
private void initContainer() {
mContainer = new FrameLayout(mContext);
mContainer.setBackgroundColor(Color.BLACK);
LayoutParams params =
new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mContainer.setLayoutParams(params);
this.addView(mContainer);
}
/**
* 设置UI 控制器
* @param controller
*/
public void setMediaController(WxMediaController controller){
Log.e("tag", " setMediaController ");
mWxMediaController = controller;
mWxMediaController.setWxPlayer(this);
mContainer.removeView(mWxMediaController);
LayoutParams params =
new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mContainer.addView(mWxMediaController,-1,params);
}
/**
* 添加TextureView
*/
private void addTextureView() {
Log.e("tag", " addTextureView ");
mContainer.removeView(mRlTextueView);
LayoutParams params =
new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mContainer.addView(mRlTextueView,0,params);
}
视频的大小处理;
我这里的处理是,width 铺满,height 根据视频的size 比例来计算,代码如下:
//首先取得video的宽和高
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
int width = getDeviceWidth(); // 对视频缩放
int height = 0;
if (mVideoWidth == 0 || mVideoHeight == 0) {
height = getDeviceHeight();
} else {
height = width * mVideoHeight / mVideoWidth;
}
根据视频size ,自适应,代码如下:
// for compatibility, we adjust size based on aspect ratio
if ( mVideoWidth * height < width * mVideoHeight ) {
width = height * mVideoWidth / mVideoHeight;
} else if ( mVideoWidth * height > width * mVideoHeight ) {
height = width * mVideoHeight / mVideoWidth;
}
注意:视频大小获取的时机,可以在OnPreparedListener
和OnVideoSizeChangedListener
回调获得。
更新播放进度条,使用Handler
发送postDelayed
:
/**
* 发送更新进条postDelayed
*/
public void startUpdateProgress() {
mHandler.postDelayed(progressRunnable, 500);
}
private Runnable progressRunnable = new Runnable() {
@Override
public void run() {
updateProgress();
startUpdateProgress();
}
};
/**
* 更新进度条
*/
private void updateProgress() {
int position = mControll.getCurrentPosition();
int duration = mControll.getDuration();
if (duration == 0) {
return;
}
int bufferPercentage = mControll.getBufferPercentage();
mSeek.setSecondaryProgress(bufferPercentage);
int progress = (int) (100f * position / duration);
mSeek.setProgress(progress);
mPosition.setText(NiceUtil.formatTime(position));
mDuration.setText(NiceUtil.formatTime(duration));
}
UML图
参考文章
用MediaPlayer+TextureView封装一个完美实现全屏、小窗口的视频播放器
END