【Android】 从头搭建视频播放器(4)——屏幕旋转处理
转载请注明出处:http://www.jianshu.com/p/eb4451923172
项目代码地址:https://github.com/Android-Jungle/android-jungle-mediaplayer
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 所代表的具体值如下:
其实就是拿手机顺时针旋转,依次将 orientation 增大 90 的过程。我们在 onOrientationChanged 回调中,根据 orientation 所处的区间,可以轻松得到应该请求的屏幕 Orientation。为了优化灵敏度,我们为每个区间的上下限个增加了 10 。具体计算过程如下:
处理 Orientation 得到了当前屏幕角度下 Activity 应该需要的 ScreenOrientation,我们就可以通过 Activity.setRequestedOrientation(int requestedOrientation)
方法来进行 Activity 屏幕角度的更改,然后整个 View 的布局就会随之更新,我们的视频画面也能得到相应的更新。
4、Activity 的处理
4.1、请求更改 Activity ScreenOrientation
具体代码如下:
SwitchScreenOrientation 可以看到我们在全屏模式下为 Activity 添加了 FLAG_FULLSCREEN
标识,让其处于全屏模式。在切换到非全屏模式的时候清除该标记即可。
4.2、Activity 的声明
为了灵活处理屏幕旋转 + 全屏半屏的切换,而不销毁 Activity,我们的 Activity 必须在声明的时候,在 configChanges
里面加上 orientation
标记:
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 zyfgood12@163.com
* @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<Context> 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>(context);
}
public ScreenOrientationSwitcher(Context context, int rate) {
super(context, rate);
mContextRef = new WeakReference<Context>(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);
}
}
}
}