【Android】 从头搭建视频播放器(4)——屏幕旋转处理


转载请注明出处:http://blog.csdn.net/arnozhang12/article/details/48736147
 
 

1、思路

        作为一款用户体验比较好的播放器,针对屏幕旋转来做适配处理是必不可少的,我们可以通过 Android SDK 提供的 OrientationEventListener 来进行处理。在屏幕旋转时,会回调到 onOrientationChanged(int orientation) 方法中,我们在这里判断旋转的角度,然后调节 Activity 的 ScreenOrientation,即可做到视频画面随手机旋转而旋转的效果。

2、OrientationEventListener

        OrientationEventListener 其实就是一个帮助类,它内部有一个 SensorEventListener,通过对手机传感器的监听处理(SensorManager),而做到屏幕旋转的判断。它的主要的方法如下

方法 特性
OrientationEventListener(context) 构造函数
enable() 启用监听,一般我们需要监听的时候调用它
disable() 停止监听,一般在 Activity 销毁之前或者不再需要监听旋转的时候调用它
onOrientationChanged(orientation) 屏幕发生了旋转

3、onOrientationChanged(int orientation)

        这个方法是最重要的一个方法了,我们可以根据所传入的参数 orientation 来判断当前屏幕所在的角度。orientation 所代表的具体值如下:

【Android】 从头搭建视频播放器(4)——屏幕旋转处理_第1张图片

        其实就是拿手机顺时针旋转,依次将 orientation 增大 90 的过程。我们在 onOrientationChanged 回调中,根据 orientation 所处的区间,可以轻松得到应该请求的屏幕 Orientation。为了优化灵敏度,我们为每个区间的上下限个增加了 10 。具体计算过程如下:

【Android】 从头搭建视频播放器(4)——屏幕旋转处理_第2张图片

        得到了当前屏幕角度下 Activity 应该需要的 ScreenOrientation,我们就可以通过 Activity.setRequestedOrientation(int requestedOrientation) 方法来进行 Activity 屏幕角度的更改,然后整个 View 的布局就会随之更新,我们的视频画面也能得到相应的更新。

4、Activity 的处理

4.1、请求更改 Activity ScreenOrientation

        具体代码如下:

【Android】 从头搭建视频播放器(4)——屏幕旋转处理_第3张图片

        可以看到我们在全屏模式下为 Activity 添加了 FLAG_FULLSCREEN 标识,让其处于全屏模式。在切换到非全屏模式的时候清除该标记即可。

4.2、Activity 的声明

        为了灵活处理屏幕旋转 + 全屏半屏的切换,而不销毁 Activity,我们的 Activity 必须在声明的时候,在 configChanges 里面加上 orientation 标记:

Activity声明

4.3、处理 onConfigurationChanged

        当调用 Activity.setRequestedOrientation 方法之后,可以在 Activity.onConfigurationChanged(Configuration newConfig) 方法中进行处理。newConfig.orientation 就是新的屏幕角度,它应该是 ActivityInfo.SCREEN_ORIENTATION_XXX 中的一个值。在这里我们应该做的操作有:

  • 调整视频播放区域的大小及布局——通过 setLayoutParams 实现
  • 按全屏/半屏状态更新相关 UI——比如各个按钮、一些界面细节的处理

        好在 Android 的各种 Layout 可以灵活的做到布局更新,我们只需要为视频播放器 StrawMediaPlayer 的跟 ViewGroup 做新的排布参数,其子 View 都会按相应的布局规则得到刷新,非常方便。

5、检测系统 “屏幕自动旋转” 开关

        为了优化体验,我们可以检测系统的 “屏幕自动旋转” 开关,在这个开关关闭的时候,我们不进行屏幕旋转的相关处理。判断这个开关状态的代码如下:

/** * 判断是否开启了 “屏幕自动旋转” */public static boolean isScreenAutoRotate(Context context) {    int gravity = 0;    try {        gravity = Settings.System.getInt(context.getContentResolver(),                Settings.System.ACCELEROMETER_ROTATION);    } catch (Settings.SettingNotFoundException e) {        e.printStackTrace();    }    return gravity == 1;}

6、代码片段

/** * ScreenOrientationSwitcher.java * * @author arnozhang * @email  [email protected] * @date   2015.9.25 */public class ScreenOrientationSwitcher extends OrientationEventListener {    private static final long MAX_CHECK_INTERVAL = 3000;    public static interface OnChangeListener {        void onChanged(int requestedOrientation);    }    private WeakReference mContextRef;    private boolean mIsSupportGravity = false;    private int mCurrOrientation = ORIENTATION_UNKNOWN;    private long mLastCheckTimestamp = 0;    private OnChangeListener mChangeListener;    public ScreenOrientationSwitcher(Context context) {        super(context);        mContextRef = new WeakReference(context);    }    public ScreenOrientationSwitcher(Context context, int rate) {        super(context, rate);        mContextRef = new WeakReference(context);    }    public void setChangeListener(OnChangeListener listener) {        mChangeListener = listener;    }    public int getCurrOrientation() {        return mCurrOrientation;    }    @Override    public void onOrientationChanged(int orientation) {        Context context = mContextRef.get();        if (context == null || !(context instanceof Activity)) {            return;        }        long currTimestamp = System.currentTimeMillis();        if (currTimestamp - mLastCheckTimestamp > MAX_CHECK_INTERVAL) {            mIsSupportGravity = MiscUtils.isScreenAutoRotate(context);            mLastCheckTimestamp = currTimestamp;        }        if (!mIsSupportGravity) {            return;        }        if (orientation == ORIENTATION_UNKNOWN) {            return;        }        int requestOrientation = ORIENTATION_UNKNOWN;        if (orientation > 350 || orientation < 10) {            requestOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;        } else if (orientation > 80 && orientation < 100) {            requestOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;        } else if (orientation > 260 && orientation < 280) {            requestOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;        } else {            return;        }        if (requestOrientation == mCurrOrientation) {            return;        }        boolean needNotify = mCurrOrientation != ORIENTATION_UNKNOWN;        mCurrOrientation = requestOrientation;        if (needNotify) {            if (mChangeListener != null) {                mChangeListener.onChanged(requestOrientation);            } else {                Activity activity = (Activity) context;                activity.setRequestedOrientation(requestOrientation);            }        }    }}

更多相关文章

  1. MPAndroidChart的一些问题解决方法
  2. Android EditText TextWatcher 回调方法参数说明
  3. Android生成界面的两种方法:setContentView和inflate的区别
  4. Android 使用Canvas在图片上绘制文字的方法
  5. android中popupwindow弹出后,屏幕背景变成半透明
  6. Android 项目快速更改包名的方法
  7. 『ANDROID』 在Android开发过程中,常Android 更新UI的两种方法—

随机推荐

  1. Rancher 2.2.5发布,CVE修复,支持K8S 1.15
  2. 新东方的Kubernetes实践:从服务化ES到Kafk
  3. spark workCount 求和
  4. 【实战案例】Ajax请求第三方接口数据利用
  5. ExFat文件系统文件误删除. 不知道如何找
  6. 喵喵的华为DevCloud使用指南(3)-项目构建
  7. 网络编程基础2
  8. BlueStore源码分析之事物状态机
  9. 分组密码与模式
  10. 微信小程序生成分享图片踩坑大计划