Android 视频播放适配横竖屏切换功能的实现

项目中视频的播放之前的设计一直是根据视频的宽高进行判断,以最大程度显示界面的方式来播放视频。目前打算适配横竖屏的切换,现在的设计是:若屏幕为竖屏锁定,播放视频就竖屏锁定;若屏幕为横屏锁定, 播放视频就横屏锁定。若屏幕自动旋转按钮打开,则横屏状态下就横屏播放,竖屏状态下就竖屏播放。下面讲解该功能的实现步骤:

一、获取屏幕锁的状态:

判断是否开启了重力感应:

public boolean screenIsOpenRotate(Context context) {

    int gravity = 0;
    try {

        gravity = Settings.System.getInt(context.getContentResolver(),

        Settings.System.ACCELEROMETER_ROTATION);

    } catch (SettingNotFoundException e) {

        e.printStackTrace();

    }
    if (gravity == 1) {

        return true;

    }

        return false;

}

Settings.System.ACCELEROMETER_ROTATION):表示设置重力感应开关

若gravity的值为1,表示开启了重力感应,返回true。即屏幕自动旋转按钮为打开状态。反之为关闭状态。

二、监听Settings 下面的屏幕锁的值的变化

   在开发Android应用的时候有时需要监听Settings下面的值(如蓝牙、飞行模式、屏幕锁 ...),这个时候可以通过ContentObserver 来监听值的变化。

1.首先自定义一个类继承ContentObserver , 在onChange()方法里面再次去获取Settings的值。

private class SettingsValueChangeContentObserver extends ContentObserver {

    public SettingsValueChangeContentObserver() {

        super(new Handler());

    }
    @Override
    public void onChange(boolean selfChange) {

        super.onChange(selfChange);

        //调用一中的方法获取屏幕锁的状态

        screenIsOpenRotate = screenIsOpenRotate(MovieActivity.this);

        //若现在为屏幕锁定,根据屏幕的方向设置activity的方向。

        if (!screenIsOpenRotate) {

            if (MovieActivity.this.getResources().getConfiguration().orientation== Configuration.ORIENTATION_LANDSCAPE) {

                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);

              } else if (MovieActivity.this.getResources().getConfiguration().orientation== Configuration.ORIENTATION_PORTRAIT) {

                  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);

              }

        }

    }

}

2.注册监听

mContentOb = new SettingsValueChangeContentObserver();
getContentResolver().registerContentObserver(Settings.System.getUriFor(

Settings.System.ACCELEROMETER_ROTATION),true, mContentOb);

3.当应用退出的时候取消监听

@Override
protected void onStop() {

    super.onStop();
    getContentResolver().unregisterContentObserver(mContentOb);

}

这时当用户在操作屏幕锁的时候就会回调 public void onChange(boolean selfChange) 方法,从而知道当前屏幕锁的状态。
PS: 大家可以去SDK中查看该类:android.provider.Settings.System。该类封装了对设置模块下所有值的存取,
比如:飞行模式状态、蓝牙状态、屏幕亮度值等,并且提供了相应的Uri。

三、处理横竖屏切换的屏幕适配
1、若当前屏幕锁未开启,即为自动旋转的状态,则使用OrientationEventListener处理自动旋转的屏幕适配。

mOrientationListener = new OrientationEventListener(this) {

    @Override
    public void onOrientationChanged(int rotation) {

        //自动旋转按钮打开,Activity的方向由物理方向传感器来决定,按照用户旋转设备的方向来显示。

        if (screenIsOpenRotate) {

            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

        }

    }

};
mOrientationListener.enable();

当不需要监听了使用mOrientationListener.disable()取消监听。

附: 设定Activity主窗口的方向,数组中的方向会设定给R.attr类中的screenOrientation属性, screenOrientation的

属性值必须是以下常量值:

ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
不指定方向,让系统决定Activity的最佳方向。
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
希望Activity在横向屏上显示,也就是说横向的宽度要大于纵向的高度,并且忽略方向传感器的影响。
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
希望Activity在纵向屏上显示,也就是说纵向的高度要大于横向的宽度,并且忽略方向传感器的影响。
ActivityInfo.SCREEN_ORIENTATION_USER:
使用用户设备的当前首选方向。
ActivityInfo.SCREEN_ORIENTATION_BEHIND:
始终保持与屏幕一致的方向,不管这个Activity在前台还是后台。
ActivityInfo.SCREEN_ORIENTATION_SENSOR:
Activity的方向由物理方向传感器来决定,按照用户旋转设备的方向来显示。
ActivityInfo.SCREEN_ORIENTATION_NOSENSOR:
始终忽略方向传感器的判断,当用户旋转设备时,显示不跟着旋转。
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
希望Activity在横向屏幕上显示,但是可以根据方向传感器指示的方向来进行改变。
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
希望Activity在纵向屏幕上显示,但是可以根据方向传感器指示的方向来进行改变。
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
希望Activity在横向屏幕上显示,但与正常的横向屏幕方向相反。
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
希望Activity在纵向屏幕上显示,但与正常的纵向屏幕方向相反
ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR:
Activity的方向由方向传感器来决定,显示会根据用户设备的移动情况来旋转。

2、若当前屏幕锁开启,则根据屏幕的方向来锁定屏幕
(1) 在ContentObserver中的处理:

public void onChange(boolean selfChange) {

    super.onChange(selfChange);
    screenIsOpenRotate = screenIsOpenRotate(MovieActivity.this);
    if (!screenIsOpenRotate) {

        if (MovieActivity.this.getResources().getConfiguration().orientation== Configuration.ORIENTATION_LANDSCAPE) {

            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);

        } else if (MovieActivity.this.getResources().getConfiguration().orientation== Configuration.ORIENTATION_PORTRAIT) {

            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);

        }

    }

}

(2)在MediaPlayer.OnVideoSizeChangedListener中的onVideoSizeChanged方法中的处理:

public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {

    super.onVideoSizeChanged(mp, width, height);
    if (MovieActivity.this.getResources().getConfiguration().orientation ==Configuration.ORIENTATION_LANDSCAPE) {

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);

    } else if (MovieActivity.this.getResources().getConfiguration().orientation ==Configuration.ORIENTATION_PORTRAIT) {

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);

    }

}

四、注意事项:

(1)这里不能使用 public void onConfigurationChanged(Configuration newConfig) 方法来处理屏幕的适配,因为在setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);方法执行之后,onConfigurationChanged方法将不再被调用。

(2)若player所在的activity实现了SensorEventListener接口,记得注释掉,防止两个Listener之间的干扰。

你可能感兴趣的:(android)