Only fullscreen opaque activities can request orientation 保持原有功能不变一行代码解决的办法

把标题的英文翻译中文就是:只有不透明的全屏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背景透明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值