模仿原生的提供的視頻播放器VideoView啸臀,封裝一個(gè)仿微信的視頻播放器。
原生的VideoView,為了解耦和方便定制禁荸,把MediaPlayer的播放邏輯和UI界面展示及操作相關(guān)的邏輯分離。
加入邊播放邊緩存的功能阀湿,引入AndroidVideoCache緩存庫(kù)赶熟。
微信的播放界面如下:
界面的設(shè)計(jì)封裝
通過(guò)FrameLayout 疊上兩層 UI Layout + TextureView。
/**
* 創(chuàng)建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);
}
/**
* 設(shè)置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 根據(jù)視頻的size 比例來(lái)計(jì)算灾挨,代碼如下:
//首先取得video的寬和高
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
int width = getDeviceWidth(); // 對(duì)視頻縮放
int height = 0;
if (mVideoWidth == 0 || mVideoHeight == 0) {
height = getDeviceHeight();
} else {
height = width * mVideoHeight / mVideoWidth;
}
根據(jù)視頻size 邑退,自適應(yīng),代碼如下:
// 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;
}
注意:視頻大小獲取的時(shí)機(jī)涨醋,可以在OnPreparedListener
和OnVideoSizeChangedListener
回調(diào)獲得瓜饥。
更新播放進(jìn)度條,使用Handler
發(fā)送postDelayed
:
/**
* 發(fā)送更新進(jìn)條postDelayed
*/
public void startUpdateProgress() {
mHandler.postDelayed(progressRunnable, 500);
}
private Runnable progressRunnable = new Runnable() {
@Override
public void run() {
updateProgress();
startUpdateProgress();
}
};
/**
* 更新進(jìn)度條
*/
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封裝一個(gè)完美實(shí)現(xiàn)全屏浴骂、小窗口的視頻播放器
END