WebView網頁視訊統一全屏播放及橫豎屏切換
阿新 • • 發佈:2018-12-21
WebView 支援 Html5 video 進行全屏播放及橫豎屏自動切換
1.檢查AndroidManifest.xml清單檔案,WebView控制元件所在的Activity配置資訊;檢查Activity的主題是否NoActionBar了。
## 犯錯的錯誤寫成了如下: android:configChanges="orientation|keyboardHidden" --> ## 正確的寫法: android:configChanges="orientation|screenSize|keyboardHidden" 或者: android:configChanges="keyboard|keyboardHidden|orientation|screenSize|navigation|fontScale|uiMode|screenLayout"
注:
總結: 1、不設定Activity的android:configChanges時,切屏會重新呼叫各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次 2、設定Activity的android:configChanges="orientation"時,切屏還是會重新呼叫各個生命週期,切橫、豎屏時只會執行一次 3、設定Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新呼叫各個生命週期,只會執行onConfigurationChanged方法 (一次生命週期)如切換成橫屏: onSaveInstanceState-->onPause-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume-->
2.初始化webview及各項setting(自己去根據需求初始化)
//常用: WebSettings ws = webView.getSettings(); // 網頁內容的寬度是否可大於WebView控制元件的寬度 ws.setLoadWithOverviewMode(false); // 儲存表單資料 ws.setSaveFormData(true); // 是否應該支援使用其螢幕縮放控制元件和手勢縮放 ws.setSupportZoom(true); ws.setBuiltInZoomControls(true); ws.setDisplayZoomControls(false); // 啟動應用快取 ws.setAppCacheEnabled(true); // 設定快取模式 ws.setCacheMode(WebSettings.LOAD_DEFAULT); // setDefaultZoom api19被棄用 // 設定此屬性,可任意比例縮放。 ws.setUseWideViewPort(true); // 不縮放 webView.setInitialScale(100); // 告訴WebView啟用JavaScript執行。預設的是false。 ws.setJavaScriptEnabled(true); // 頁面載入好以後,再放開圖片 ws.setBlockNetworkImage(false); // 使用localStorage則必須開啟 ws.setDomStorageEnabled(true); // 排版適應螢幕 ws.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS); // WebView是否新視窗開啟(加了後可能打不開網頁) ws.setSupportMultipleWindows(true); // webview從5.0開始預設不允許混合模式,https中不能載入http資源,需要設定開啟。 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ws.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } /** 設定字型預設縮放大小(改變網頁字型大小,setTextSize api14被棄用)*/ ws.setTextZoom(100);
3.給WebView設定WebViewClient:
思路:在onShowCustomView方法中,講獲取到的view放到當前Activity的最上方,在onHideCustomView中,將之前的view隱藏或者刪除,將原來被覆蓋的webview放回來。並結束播放。
webView.setWebViewClient(new MyWebViewClient(this));
//webview視訊全屏下videoContainer ---(自己在webview所在佈局裡定義一個frameLayout作為盛放view的容器) private CustomVideoContainerFramLayout mVideoContainer; //webview全屏時傳入的view private View mXCustomView; public class NewsWebViewChromeClient extends WebChromeClient { /** * webview全屏回撥 * * @param view * @param callback */ @Override public void onShowCustomView(View view, CustomViewCallback callback) { super.onShowCustomView(view, callback); //設定全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //設定橫屏 int requestedOrientation = getRequestedOrientation(); if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE) { //反橫屏下設定跟隨感測器 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); } else { //其他情況設定橫屏 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } if (webview != null) { webview.setVisibility(View.GONE); } if (mXCustomView != null) { callback.onCustomViewHidden(); return; } fullViewAddView(view); mXCustomView = view; mVideoContainer.setVisibility(View.VISIBLE); //設定隱藏虛擬按鍵/導航鍵(避免造成全屏時佈局不滿) mXCustomView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE); } /** * webview 退出全屏回撥 */ @Override public void onHideCustomView() { if (mXCustomView == null) { // 不是全屏播放狀態 return; } //取消全屏 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); //恢復虛擬鍵 mXCustomView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); //恢復為使用者方向 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER); mXCustomView.setVisibility(View.GONE); if (mVideoContainer != null) { mVideoContainer.removeView(mXCustomView); } mXCustomView = null; mVideoContainer.setVisibility(View.GONE); if (webview != null) { webview.setVisibility(View.VISIBLE); } } } public void fullViewAddView(View view) { FrameLayout decor = (FrameLayout) getWindow().getDecorView(); mVideoContainer = new CustomVideoContainerFramLayout(this); mVideoContainer.addView(view); decor.addView(mVideoContainer); }
開啟重力感應自動切換螢幕
使用方法:
//重力感測器
private MySensorHelper sensorHelper;
private void initData() {
//初始化重力感應,傳入activity
sensorHelper = new MySensorHelper(this);
//開啟重力感應
sensorHelper.enable();
}
@Override
protected void onDestroy() {
//關閉重力感測器
if (sensorHelper != null) {
sensorHelper.disable();
}
}
4.開啟重力感應自動切換螢幕
使用方法:
//重力感測器
private MySensorHelper sensorHelper;
private void initData() {
//初始化重力感應,傳入activity
sensorHelper = new MySensorHelper(this);
//開啟重力感應
sensorHelper.enable();
}
@Override
protected void onDestroy() {
//關閉重力感測器
if (sensorHelper != null) {
sensorHelper.disable();
}
}
直接上程式碼:具體可根據需求進行更改
/**
* @author : Created by zhangqiang
* @date : on 2018/9/30.
* desc :通過重力感測器切換橫豎屏放向
* 在activity的ondestory()方法裡面或者back鍵的監聽裡面禁用螢幕監聽
*/
public class MySensorHelper {
private static final String TAG = "MySensorHelper";
private OrientationEventListener mOrientationEventListener;
private WeakReference<Activity> mActivityWeakRef;
private Activity mActivity;
//豎直鎖定
private boolean isPortLock = false;
//橫屏鎖定
private boolean isLandLock = false;
//是否在全屏模式
private boolean isFullScreen = false;
//螢幕方向
private int mOrientation = -1;
//螢幕狀態 (橫屏 / 豎屏等)
private ScreenState mScreenState;
public MySensorHelper(final Activity activity) {
this.mActivityWeakRef = new WeakReference(activity);
mActivity = activity;
//橫屏感應
this.mOrientationEventListener = new OrientationEventListener(activity, SensorManager.SENSOR_DELAY_NORMAL) {
@Override
public void onOrientationChanged(int orientation) {
if (BuildConfig.DEBUG) {
Log.v(MySensorHelper.TAG, "mOrientationEventListener:" + orientation);
}
// //若未開啟重力感應則不作處理
// if (!ishaveSensor()) {
// return;
// }
//橫屏感應
if (orientation < 100 && orientation > 80 || orientation < 280 && orientation > 260) {
if (!MySensorHelper.this.isLandLock) {
Activity mActivity = (Activity) MySensorHelper.this.mActivityWeakRef.get();
if (mActivity != null) {
if (orientation < 280 && orientation > 260) {
/* 在全屏模式下 或者 開啟了重力感應下 才進入旋轉 */
if (isFullScreen || ishaveSensor()) {
//設定橫屏
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
if (BuildConfig.DEBUG) {
Log.w(MySensorHelper.TAG, "轉到了橫屏##################");
}
}
} else if (orientation < 100 && orientation > 80) {
//在全屏模式下 或者 開啟了重力感應下 才進入旋轉
if (isFullScreen || ishaveSensor()) {
//設定反向橫屏
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
if (BuildConfig.DEBUG) {
Log.w(MySensorHelper.TAG, "轉到了橫屏-反向 ##################");
}
}
}
isLandLock = true;
isPortLock = false;
}
}
}
// 豎屏感應
if (orientation < 10 || orientation > 350 || orientation < 190 && orientation > 170) {
if (!MySensorHelper.this.isPortLock) {
Activity mActivity = (Activity) MySensorHelper.this.mActivityWeakRef.get();
if (mActivity != null) {
if (isFullScreen) {
//全屏下 若未開啟方向鎖定 呼叫webview全屏消失
if (mScreenState != null && ishaveSensor()) {
mScreenState.OnScreenPortrait();
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
if (BuildConfig.DEBUG) {
Log.w(MySensorHelper.TAG, "全屏下 轉到了豎屏!!!!!!!!!!!!!!!!!!!!!!");
}
}
} else {
//非全屏下才處理 感應旋轉
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
if (BuildConfig.DEBUG) {
Log.w(MySensorHelper.TAG, "非全屏下 轉到了豎屏!!!!!!!!!!!!!!!!!!!!!!");
}
}
isPortLock = true;
isLandLock = false;
}
}
}
}
};
}
/**
* 禁用切換螢幕的開關
*/
public void disable() {
Log.e(TAG, "disable");
//禁用橫屏感應
if (mOrientationEventListener != null) {
this.mOrientationEventListener.disable();
}
}
/**
* 開啟橫豎屏切換的開關
*/
public void enable() {
//橫屏感應
if (mOrientationEventListener != null) {
this.mOrientationEventListener.enable();
}
}
/**
* 設定豎屏是否上鎖,true鎖定螢幕,fanle解鎖
*
* @param lockFlag
*/
public void setPortLock(boolean lockFlag) {
this.isPortLock = lockFlag;
}
/**
* 設定橫屏是否鎖定,true鎖定,false解鎖
*
* @param isLandLock
*/
public void setLandLock(boolean isLandLock) {
this.isLandLock = isLandLock;
}
/**
* 設定當前是否全屏
*
* @param fullScreen
*/
public void setFullScreen(boolean fullScreen) {
this.isFullScreen = fullScreen;
}
/**
* 獲取系統重力感應的開關狀態
* 0表示關閉,1表示開啟
*/
public boolean ishaveSensor() {
int sensor = 0;
try {
sensor = Settings.System.getInt(mActivity.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
if (sensor == 0) {
return false;
} else {
return true;
}
}
/**
* Activity當前螢幕方向的屬性值
*
* @return 0 橫屏 , 1 豎屏
*/
public int getOrientation() {
if (mActivity != null && !mActivity.isFinishing()) {
mOrientation = mActivity.getResources().getConfiguration().orientation;
return mOrientation;
}
return -1;
}
/**
* 設定Activity的的螢幕方向屬性值
*
* @param orientation ActivityInfo.xxx 0 橫屏 , 1 豎屏 如ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
* <p>
* screenOrientations屬性共有7中可選值(常量定義在 android.content.pm.ActivityInfo類中 ) :
* 0-landscape:橫屏(風景照) ,顯示時寬度大於高度;
* portrait:豎屏 (肖像照) , 顯示時 高 度大於 寬 度 ;
* user:使用者當前的首選方向;
* behind:繼承Activity堆疊中當前Activity下面的那個Activity的方向;
* sensor:由物理感應器決定顯示方向,它取決於使用者如何持有裝置,當 裝置 被旋轉時方向會隨之變化——在橫屏與豎屏之間;
* nosensor:忽略物理感應器——即顯示方向與物理感應器無關,不管使用者如何旋轉裝置顯示方向都不會隨著改變("unspecified"設定除外);
* unspecified :未指定,此為預設值,由Android系統自己選擇適當的方向,選擇策略視具體裝置的配置情況而定,因此不同的裝置會有不同的方向選擇;
* 以上配置值會反映在Activity.getRequestedOrientation()方法的返回值中,與之對應的setRequestedOrientation()方法可以通過API的方式動態改變該屬性的值,如以下示例將在橫屏/豎屏兩個方向上進行切換
*/
public void setOrientation(int orientation) {
mOrientation = orientation;
mActivity.setRequestedOrientation(orientation);
}
/**
* 設定螢幕狀態(橫屏/豎屏監聽)
*
* @param screenState
*/
public void setScreenStateListener(ScreenState screenState) {
mScreenState = screenState;
}
/**
* 螢幕狀態介面類
*/
public interface ScreenState {
/**
* 豎屏狀態
*/
void OnScreenPortrait();
}
}
相關參考: