把标题的英文翻译中文就是:只有不透明的全屏Activity才可以设置它的orientation属性
这个crash只有在android 8.0的设备上才会出现,Android8.1中已经修复了
出现这个问题是主要因为我们主题样式里设置了Activity透明背景
<item name="android:windowIsTranslucent">true</item>
同时设置了Activity固定横屏或者竖屏,例如:
android:screenOrientation="portrait"
或者:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
网上有些文章对这个问题分析的很透彻,解决的办法很多都是让我们放弃例如“侧滑关闭”这类需要背景透明的功能,也就是把Activity改为不透明,或者就是改为不要固定横屏或者竖屏,稍微好点的解决方案是:滑动前设置背景透明,滑动后再设置不透明,但是分析一下源码发现其实都不用那么麻烦,一行代码就可以搞定的。
在BaseActivity里的onCreate方法里加上下面这句就行了:
getWindow().getDecorView().setBackgroundColor(Color.TRANSPARENT);//将Activity的背景色设置为透明
也就是把之前主题style里设置Activity背景透明改为用代码实现,这样不管你有没有设置固定横竖屏或者全屏都不会崩溃,为什么主题里设置不行,代码里设置就行呢?我们来看看源码就知道。
下面这个代码就是崩溃出现的源头:
if (getApplicationInfo().targetSdkVersion > O && mActivityInfo.isFixedOrientation()) {//判断是否固定了横竖屏
final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);//判断是否设置了透明或者悬浮、右滑
ta.recycle();
if (isTranslucentOrFloating) {
throw new IllegalStateException(
"Only fullscreen opaque activities can request orientation");
}
}
下面是判断是否设置透明或者悬浮、右滑的方法:
public static boolean isTranslucentOrFloating(TypedArray attributes) {
final boolean isTranslucent =
attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent,
false);//是否设置背景透明
final boolean isSwipeToDismiss = !attributes.hasValue(
com.android.internal.R.styleable.Window_windowIsTranslucent)
&& attributes.getBoolean(
com.android.internal.R.styleable.Window_windowSwipeToDismiss, false);//是否启用右滑功能
final boolean isFloating =
attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating,
false);//是否悬浮
return isFloating || isTranslucent || isSwipeToDismiss;
}
从上面这个方法可以看得出,它判断是否透明或者悬浮、右滑都是通过读取主题样式里的属性来的,也就是如果用代码实现的,它是没有进行判断的,这也就解释了为什么主题里配置不行,代码里实现却可以。
从源码上看,在Android8.0我们不仅仅要注意Activity透明背景问题,如果在主题里设置了windowSwipeToDismiss或者windowIsFloating属性值为true,也是会导致crash的
=============================================
后面发现部分手机不在主题里设置背景透明Activity跳转时动画异常或者有部分闪黑,于是改变了处理方式:默认的主题设置背景透明,新建values-v26文件夹,styles.xml里指定Android8.0的主题背景不透明,然后在BaseActivity里判断只有Android8.0系统才使用代码设置Activity背景透明