前段时间产品说要给直播间加个自动转屏,比较迷惑,因为自动转屏的话,躺着用聊天模式很容易误操作,基本没有直播平台采用自动转屏来切全屏,基本都是双击播放器切全屏。不过产品倒是很坚持,一直说先做上去看看效果,那就做呗。(埋点啥的也没有咋看效果,看客服投诉么2333)
提到转屏回调首先就想到了onConfigurationChanged()
方法,所以就按这个方法出触发的事件监听写了个自动转屏方案
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Display getOrient = getWindowManager().getDefaultDisplay();
int orientation;
if(getOrient.getWidth() < getOrient.getHeight()){
orientation = Configuration.ORIENTATION_PORTRAIT;
}else {
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
switchOrientation(orientation); // 此方法内部主要是按横竖屏方向调整具体布局,不赘述
}
不过实践下来发现并不可取,有几点问题
- 不够灵敏,有的时候手机已经完全横过来了但却没有转屏,还要转两下子……
- 大幅度旋转,很有可能不会触发,比如一下子横屏旋转180度(躺在床上翻个身这种)
要做更灵敏准确的自动转屏肯定不能靠这个了,研究了一下,可以通过设置OrientationEventLister
监听手机旋转角度。经过调试之后的自动转屏控制方法如下:
orientationEventListener = new OrientationEventListener(this) {
@Override
public void onOrientationChanged(int rotation) {
if (!isSystemRotationEnabled()) {
orientationEventListener.disable();
return;
}
// UI按键锁定,不允许横竖屏切换
if (isLock) {
return;
}
// clickSwitchProtect用于在用户横着手机时点按钮切回竖屏时保持竖屏状态,
// 或者竖着手机切横屏时保持状态,避免通过按钮切过去又马上被转回来
// 在手机角度改变到与当前布局方向一致时取消保护
if (rotation >= 345 && rotation <= 360 || rotation >= 0 && rotation <= 15) {
if (clickSwitchProtect && !isFullScreen) {
clickSwitchProtect = false;
}
if (!isFullScreen || clickSwitchProtect) {
return;
}
switchOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else if (rotation >= 75 && rotation <= 105) {
if (clickSwitchProtect && isFullScreen) {
clickSwitchProtect = false;
}
if (clickSwitchProtect) {
return;
}
int winRotation = getWindowManager().getDefaultDisplay().getOrientation();
if (winRotation == Surface.ROTATION_270 && isFullScreen) {
return;
}
switchOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
}
else if (rotation >=255 && rotation <= 285) {
if (clickSwitchProtect && isFullScreen) {
clickSwitchProtect = false;
}
if (clickSwitchProtect) {
return;
}
int winRotation = getWindowManager().getDefaultDisplay().getOrientation();
if (winRotation == Surface.ROTATION_90 && isFullScreen) {
return;
}
switchOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
};
注意,由于OrientationEventLister
是无视系统的屏幕旋转锁定的,为了跟系统设置保持一致,需要对系统的屏幕旋转锁定进行监听
orientationObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
if (isSystemRotationEnabled()) {
orientationEventListener.enable();
} else {
orientationEventListener.disable();
}
}
};
另外还要注意的一点是,为避免对传感器长时间占用,需要及时注册/解除注册监听,建议在 onResume()
和 onPause()
中进行。
@Override
protected void onResume() {
super.onResume();
if (isSystemRotationEnabled()) {
orientationEventListener.enable();
}
getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION),
true, orientationObserver);
}
@Override
protected void onPause() {
super.onPause();
orientationEventListener.disable();
getContentResolver().unregisterContentObserver(orientationObserver);
}
之所以不在onCreate()和onDestroy()中执行注册/解除注册,主要是因为如果用户在直播间锁屏或者退回Launcher,页面还是处于栈顶,并没有被销毁,就会造成长时间占用传感器。
这是提交审核后华为渠道那边反馈的问题,不得不说华为渠道的审核还是挺严格的,某种角度来说,对华为用户是好事。