昨天晚上参加公司组织的篮球赛 ,一共打了两个小时 ,走的时候双腿有点飘胳膊都软了。真的是打球打到腿软 ,记得几年前去爬过一次长城 ,休息一晚上之后起来大腿在疼 ,今天早上起来发现手腕好像有点僵硬 ,大概是我控球太给力吧 。其实根本原因还是身体素质差点意思 ,在此建议广大同行不要老写代码定时出去溜溜 。
在优化接手项目中的遗留 BUG ,优化的我脑壳疼 。其中对于视频播放这块有几个关于横竖屏的问题 ,感觉挺有意思的可能其他小伙伴也会遇到 ,就在这边简单的记录一下 。
Android 横竖屏在项目中出现的频率还是挺高的 ,如果你的页面没有横屏的需求那也是需要在 Manifests 中进行强制横屏和竖屏的属性设置 ,否则的话就要考虑一下横竖屏切换生命的问题 。如果页面是视频有横竖屏切换的需求 ,我这边的做法也是进行竖屏设置了 ,只能用点击事件切换横竖屏 这样做没别的意思就是少些一点代码 。
系统设置的自动旋转
(1)需要打开手机的自动旋转 。
(2)去掉清单文件 Manifests 的 screenOrientation 属性 。
这样的话就可以在根据手机横竖屏的场景下进行自动切换 ,但是如果是视频或者其他需要横竖屏改变布局页面的时候就需要在回调 onConfigurationChanged 方法里面进行逻辑处理 。需要注意的点是生命周期的变化 。
代码实现的横竖屏设置
代码实现的的横竖屏切换是使用 Activity 的 setRequestOrientation 函数 。在视频页面几乎是必备的调用函数 。在配置清单中需要进行设置的 screenOrientation 和 configChanges 属性 。如何设置取决于你的需求吧 ,比如视频页面可以自动切换也可手动切换的功能 、再比如切换的时候是否进行生命周期的改变 。
设置横竖屏函数
// 横屏切换
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//竖屏切换
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
重点说一下横竖切换时候的生命周期 ,项目优化的 BUG 就是出现在这个生命周期的问题上 ,主要是在清单文件中 configChanges 属性设置有问题 。configChanges 的属性我们只关注 keyboardHidden 、orientation 、screenSize 这三个 。此属性决定的是横竖屏切换的时候生命周期的变化 (PS :Android 6.0 、7.0 、8.0 对这个 configChanges 属性还是有区分的 ,同样的值会出现不同的生命周期调用)。此处咱们只区分有没有使用 screenSize 。
configChanges 值为 keyboardHidden 、orientation 、screenSize
横竖屏切换对 Activity 的生命周期无影响 ,可以把处理逻辑全放在 onConfiggurationChanged 函数中
伪代码如下
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// 此时为横屏
// ...
} else {
// 此时为横屏
// ...
}
}
configChanges 值为 keyboardHidden 、orientation
横竖切换对生命周期有影响 。
切换横竖屏生命周期变化 ,严格一点的话 Android 6.0 、7.0 、 8.0 是有区分的 。可以自己跑一下看看 。
onPause ---- onSaveInstanceState ---- onStop ---- onDestroy ---- onCreate ---- onStart ---- onRestoreInstanceState ---- onResume ---- onPause ---- onStop ---- onDestroy
PS:2020/01/09 这次版本需要需要加上自动横竖屏切换功能 ,之前是手动的。
简单一点就是把手动的代码复制到 onConfigurationChanged 里面 。
例如
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(CommonUtil.dp2px(mActivity, 120), CommonUtil.dp2px(mActivity, 90));
ViewGroup.LayoutParams layoutParams = fl_big_layout.getLayoutParams();
ViewGroup.LayoutParams iv_bgLayoutParams = iv_bg.getLayoutParams();
ViewGroup.LayoutParams layoutParamsSpeed = ll_speed.getLayoutParams();
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// 此时为横屏
mIsFullScreen = true;
layoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = LinearLayout.LayoutParams.MATCH_PARENT;
layoutParamsSpeed.width = LinearLayout.LayoutParams.MATCH_PARENT;
layoutParamsSpeed.height = LinearLayout.LayoutParams.MATCH_PARENT;
iv_bgLayoutParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
iv_bgLayoutParams.height = LinearLayout.LayoutParams.MATCH_PARENT;
iv_bg.setLayoutParams(iv_bgLayoutParams);
fl_big_layout.setLayoutParams(layoutParams);
ll_speed.setLayoutParams(layoutParamsSpeed);
ll_setting.setVisibility(View.GONE);
cb_danmu.setVisibility(View.VISIBLE);
danmuView.setVisibility(View.VISIBLE);
iv_full_screen.setImageResource(R.mipmap.iv_small_screen);
fl_little_layout.setScreenFull(true);
fl_little_layout.setIsOnTouchEvent(true);
params.rightToRight = ConstraintLayout.LayoutParams.PARENT_ID;
params.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
fl_little_layout.setLayoutParams(params);
} else {
// 此时为横屏
mIsFullScreen = false;
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = getResources().getDimensionPixelSize(R.dimen.xdp_220);
layoutParamsSpeed.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParamsSpeed.height = getResources().getDimensionPixelSize(R.dimen.xdp_220);
iv_bgLayoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
iv_bgLayoutParams.height = getResources().getDimensionPixelSize(R.dimen.xdp_220);
iv_bg.setLayoutParams(iv_bgLayoutParams);
fl_big_layout.setLayoutParams(layoutParams);
ll_speed.setLayoutParams(layoutParamsSpeed);
ll_setting.setVisibility(View.VISIBLE);
cb_danmu.setVisibility(View.GONE);
danmuView.setVisibility(View.GONE);
fl_little_layout.setScreenFull(false);
fl_little_layout.setIsOnTouchEvent(false);
iv_full_screen.setImageResource(R.mipmap.iv_full_screen);
params.rightToRight = ConstraintLayout.LayoutParams.PARENT_ID;
params.topToBottom = R.id.fl_big_layout;
fl_little_layout.setLayoutParams(params);
}
}
出现一个小瑕疵
在旋转手机自动切换到横屏的时候 ,你点击右下角的 ICON 在切换到竖屏 没问题 ,但是你要是在想旋转手机自动切换到横屏的话就不行了 ,为啥呢 ?
原因先不说 ,估计的去看源码 ,你可以先想一下这个两个需求 ,手动设置完竖屏的时候你的重力感应此时还是在横屏 ,所以我猜手动设置完之后系统会把重力感应的这个功能给禁掉 。果然就是这样 。
解决方案 :
1. 从产品角度去解决 ,我看腾讯视频和对爱课堂中 ,是在横屏的时候把设置竖屏的icon跟隐藏 ,意思是你只要横屏的话 那你就不能再手动竖屏 。是个招呀 。
2.从技术角度有两种方案 ,第一 :使用重力感应监听者 SensorEventListener 做一些逻辑判断 ;第二 :在手动切换竖屏的时候加一行代码 如下 。
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
OKOK 、、、、