上篇文章中写道了关于H5页面中使用webview加载video.js全屏视频无法播放的问题,后续又发现了一个新的适配问题,就是全屏返回后,如果当前H5页面中有类似搜索框一样需要调起系统软键盘的操作的话,就会发现这个时候掉不起来了,一定要当前页面执行了onPause方法之后再返回才正常。这个就是由于使用了bringToFront()方法,这个方法会使当前控件脱离父布局的约束,并且覆盖到父布局上方,导致全屏视频返回后看到的webview页面并不是在真正的前台展示。仅针对这个问题对webview中加载video.js无法全屏播放的问题做如下修改处理
开启硬件加速和横竖屏切换
找到webview所在的acvitity的manifest文件配置,开启硬件加速和横屏切换,避免声明周期切换。
<activity
android:name=".home.HomeActivity"
android:launchMode="singleTop"
android:hardwareAccelerated="true"
android:screenOrientation="portrait"
android:configChanges="orientation|screenSize|keyboardHidden"
android:windowSoftInputMode="stateHidden|stateAlwaysHidden|adjustPan">
</activity>
webview所在xml文件
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fl_video">
<wendu.dsbridge.DWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
自定义设置WebChromeClient
在webview的父容器acvitity或者fragment中自定义内部类WebChromeClient
重写其中的onShowCustomView(全屏时调用)和onHideCustomView(竖屏时调用)两个方法
private class MyWebChromeClient extends WebChromeClient {
private CustomViewCallback mCustomViewCallback;
// 横屏时,显示视频的view
private View mCustomView;
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
if (mCustomView != null) {
callback.onCustomViewHidden();
return;
}
mCustomView = view;
// mCustomView.setVisibility(View.VISIBLE);
mCustomViewCallback = callback;
fl_video.addView(mCustomView);
webView.setVisibility(View.GONE);
// fl_video.setVisibility(View.VISIBLE);
// fl_video.bringToFront();
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
@Override
public void onHideCustomView() {
webView.setVisibility(View.VISIBLE);
super.onHideCustomView();
if (mCustomView == null) {
return;
}
mCustomView.setVisibility(View.GONE);
fl_video.removeView(mCustomView);
mCustomView = null;
// fl_video.setVisibility(View.GONE);
try {
if (mCustomViewCallback != null){
mCustomViewCallback.onCustomViewHidden();
}
} catch (Exception e) {
e.printStackTrace();
}
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏
webView.scrollBy(0,-200);
EventBus.getDefault().post("onHideCustomView");
super.onHideCustomView();
}
}
我的webview是在fragment中,如果是在fragment中使用
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
来设置横屏
横竖屏切换监听
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
switch (newConfig.orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
break;
case Configuration.ORIENTATION_PORTRAIT:
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
break;
}
}
websetting配置
@RequiresApi(api = Build.VERSION_CODES.M)
private void initWebSetting() {
if (webView!=null){
webView.addJavascriptObject(new JsApi(), null);
}else {
return;
}
final WebSettings webSettings = webView.getSettings();
// 设置WebView属性,能够执行Javascript脚本
webSettings.setAllowFileAccess(true);// 设置允许访问文件数据
webSettings.setDomStorageEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setBuiltInZoomControls(false);
webSettings.setJavaScriptEnabled(true);
webSettings.setTextZoom(100);
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//设置webview缓存模式
webView.setVerticalScrollBarEnabled(false); // 取消Vertical ScrollBar显示
webView.setHorizontalScrollBarEnabled(false); // 取消Horizontal ScrollBar显示
//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
webView.setWebChromeClient(new MyWebChromeClient());
webView.setWebViewClient(new WebViewClient() {
@Override
public void onScaleChanged(WebView view, float oldScale, float newScale) {
super.onScaleChanged(view, oldScale, newScale);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (url.contains("login")){
Constants.isRefreshCourse=true;
}
super.onPageStarted(view, url, favicon);
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
// super.onReceivedSslError(view, handler, error);
//默认的处理方式,WebView变成空白页
// handler.cancel();
//接受证书
handler.proceed();
//其他处理
// handleMessage(Message msg);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
});
}
fragment所在的acvitity中重新渲染页面
@Subscribe(threadMode = ThreadMode.MAIN)
public void onHideCustomViewEvent(String onHideCustomViewMsg) {
if ("onHideCustomView".equals(onHideCustomViewMsg)){
oldtabname = "";
switchFragmentShow("tabHome");
}
}
至此就实现了webview中加载包含video.js的H5页面,视频全屏播放的问题。并且视频全屏恢复返回的时候不影响当前页面的搜索框的功能,不会导致H5的搜索框获取不到焦点。可能最后一步的操作要因人而异,我这个都是在fragment中处理的,使用了eventbus事件机制,如果是在acvitity中处理思路也是一样的,重新渲染页面让当前webview回到前台就好了。