前段時(shí)間項(xiàng)目遇到一個(gè)用H5播放視頻的需求吃粒,要求能全屏播放視頻,但是WebView原生并沒(méi)有實(shí)現(xiàn)全屏播放的需求赞别,不過(guò)也并沒(méi)有完全無(wú)法實(shí)現(xiàn)全屏焦履,通過(guò)WebChromeClient來(lái)暴露了兩個(gè)接口:onShowCustomView和onHideCustomView來(lái)控制全屏播放的顯示與隱藏,可以通過(guò)這兩個(gè)方法來(lái)實(shí)現(xiàn)視頻的全屏播放功能视卢。下邊分析一下具體的需求:
1踱卵、需求
1、能全屏播放視頻
2据过、全屏播放時(shí)需要展示title(可以為手動(dòng)傳入惋砂,默認(rèn)截取域名)
3、title動(dòng)畫(huà)效果
4绳锅、title樣式(高度背景顏色和返回按鈕可配置)
5西饵、返回鍵響應(yīng)
2、實(shí)現(xiàn)
WebChromeClient實(shí)現(xiàn)如下:
WebChromeClient chromeClient = new WebChromeClient() {
@Nullable
@Override
public View getVideoLoadingProgressView() {
return super.getVideoLoadingProgressView();
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
showCustomView(view, callback);
//展示全屏設(shè)置為橫屏
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
@Override
public void onHideCustomView() {
hideCustomView();
//隱藏全屏設(shè)置為豎屏
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
};
除了showCustomView和hideCustomView兩個(gè)方法外鳞芙,還需要根據(jù)全屏的展示和隱藏來(lái)設(shè)置Activity的橫豎屏眷柔。下邊來(lái)看展示和隱藏全屏的兩個(gè)方法的具體代碼:
private void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
if (mCustomView != null) {
if (callback != null) {
callback.onCustomViewHidden();
}
return;
}
FrameLayout decorView = (FrameLayout) mActivity.getWindow().getDecorView();
decorView.setBackgroundColor(Color.BLACK);
mFullContainerView = new FrameLayout(mActivity) {
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (mTitleView != null) {
if (!mTitleShow) {
mTitleShow = true;
if (mHideAnimator != null) {
mHideAnimator.cancel();
}
mShowAnimator = ObjectAnimator.ofFloat(mTitleView, ALPHA, mShowAlpha, 1);
mShowAnimator.setDuration(1000);
mShowAnimator.start();
hideTitleView();
} else {
mTitleShow = false;
if (mShowAnimator != null) {
mShowAnimator.cancel();
}
mHideAnimator = ObjectAnimator.ofFloat(mTitleView, ALPHA, 1, 0);
mHideAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mShowAlpha = (float) ((ObjectAnimator) animation).getAnimatedValue();
super.onAnimationEnd(animation);
}
});
mHideAnimator.setDuration(1000);
mHideAnimator.start();
if (mHideRun != null) {
mHandler.removeCallbacks(mHideRun);
}
}
}
}
return super.dispatchTouchEvent(ev);
}
};
mFullContainerView.setBackgroundColor(Color.BLACK);
mFullContainerView.addView(view, FULL_SCREEN_PARAMS);
if (mIsShowTitleView) {
if (mTitleView == null) {
mTitleView = createTitleView();
}
mFullContainerView.addView(mTitleView);
mTitleShow = true;
hideTitleView();
}
decorView.addView(mFullContainerView, FULL_SCREEN_PARAMS);
mCustomView = view;
setStatusBarVisibility(false);
mCustomViewCallBack = callback;
}
首先判斷全屏View是否為空,不為空說(shuō)明當(dāng)前還處在全屏狀態(tài)原朝,作為異常處理驯嘱,調(diào)用WebChromeClient.CustomViewCallback的onCustomViewHidden()方法隱藏全屏。接著獲取當(dāng)前Activity的DecorView竿拆,作為容器來(lái)容納全屏播放的View宙拉。創(chuàng)建一個(gè)FrameLayout對(duì)象來(lái)作為全屏播放的容器,在創(chuàng)建時(shí)丙笋,對(duì)dispatchTouchEvent方法進(jìn)行了復(fù)寫(xiě)谢澈,用來(lái)實(shí)現(xiàn)title展示的動(dòng)畫(huà)效果,其中的hideTitleView()內(nèi)部是用Handler實(shí)現(xiàn)了一個(gè)2秒鐘后title消失的定時(shí)器御板。參數(shù)中的view是視頻的容器锥忿,將其加入到我們創(chuàng)建的容器中,然后將自定義實(shí)現(xiàn)的TitleView加入其中怠肋。最后將我們創(chuàng)建的容器放入Activity的容器中敬鬓。接下來(lái)是隱藏全屏的具體代碼;
private void hideCustomView() {
if (mCustomView == null) {
return;
}
setStatusBarVisibility(true);
FrameLayout decorView = (FrameLayout) mActivity.getWindow().getDecorView();
decorView.removeView(mFullContainerView);
mFullContainerView = null;
mCustomView = null;
mCustomViewCallBack.onCustomViewHidden();
mTitleView = null;
mTitleShow = false;
mHandler.removeCallbacks(mHideRun);
mHandler = null;
setVisibility(VISIBLE);
}
首先就是一場(chǎng)情況判斷笙各,如果mCustomView為空钉答,表示當(dāng)前不在全屏狀態(tài),則不用繼續(xù)執(zhí)行下邊的代碼杈抢,直接返回数尿。然后設(shè)置顯示狀態(tài)欄,并將全屏展示的View從Activity的容器中移除惶楼。并將實(shí)現(xiàn)動(dòng)畫(huà)效果的Handler移除右蹦。接下來(lái)處理返回按鈕點(diǎn)擊事件:
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (mCustomView != null) {
hideCustomView();
} else if (canGoBack()) {
goBack();
} else {
mActivity.finish();
}
return true;
default:
return super.onKeyUp(keyCode, event);
}
}
優(yōu)先級(jí)為:隱藏全屏-網(wǎng)頁(yè)回退-銷(xiāo)毀當(dāng)前Activity诊杆。這些都完成以后,就擁有了一個(gè)可以全屏播放視頻的WebView何陆。
備注:必須將使用該WebView的Activity在AndroidManifest中設(shè)置為android:configChanges="orientation|screenSize|keyboardHidden"晨汹,不然會(huì)在全屏?xí)r重新執(zhí)行Activity的生命周期,導(dǎo)致頁(yè)面重繪贷盲。另該WebView已上傳至JCenter淘这,若需要使用,則在build.gradle中添加依賴即可巩剖。
implementation 'com.wanggle.videowebview:videowebview:1.0.1'