WebView网页视频统一全屏播放及横竖屏切换

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011200604/article/details/84073706

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();
    }
}

相关参考:

WebView实现全屏播放的一种方法 https://www.jianshu.com/p/d70a73594b71 

WebView中的视频全屏4种方法,特别是腾讯视频,真正解决全屏问题   https://www.jianshu.com/p/4aed5c1230dc

WebView 支持 Html5 video 进行全屏播放   https://www.jianshu.com/p/2dd60e6bd798

 

Android 关于WebView全方面的使用(项目应用篇)      ---     github:https://github.com/youlookwhat/WebViewStudy

WebView视屏全屏切换,完美实现

WebView实现全屏播放的一种方法

Android webview网页视频无法全屏解决(onShowCustomView不调用)

webview点击全屏代码 

 android webview: 视频全屏播放按返回页面被放大的问题

android:configChanges="keyboard|keyboardHidden|orientation|screenSize" : 

 

系统重力感应开关和Activity的屏幕方向属性值之间的区别

android通过重力传感器切换横竖屏放向

让android程序根据重力感应旋转屏幕(支持4个方向旋转)

具体怎么使用视频播放屏幕的感重力切换横竖屏

Android-加速传感器或者OrientationEventListener做横竖屏切换

 

Android手势检测——GestureDetector全面分析 https://blog.csdn.net/totond/article/details/77881180

Android视频播放器的手势控制实现  https://blog.csdn.net/totond/article/details/77881403     Git :  https://github.com/totond/GestureTest

触摸事件与手势监听--Android GestureDetector详解  https://blog.csdn.net/hpk1994/article/details/51224228

 

Android设置屏幕亮度的两种方式 : https://blog.csdn.net/jiangxuelei_2015/article/details/51243575

Android设置屏幕亮度 : https://blog.csdn.net/wzy_1988/article/details/49472611

Android 6 完美解决 WRITE_SETTINGS 权限设置问题  https://www.jianshu.com/p/0b880871b887

 

webview 播放H5视频问题 黑屏 只有声音没有画面 https://www.cnblogs.com/qianyukun/p/4792533.html

hardwareAccelerated 硬件加速详解  https://blog.csdn.net/mafei852213034/article/details/50678493

详解Android开发中硬件加速支持的使用方法 https://www.jb51.net/article/79841.htm

猜你喜欢

转载自blog.csdn.net/u011200604/article/details/84073706