前言: 为什么会选这个话题

由于项目老旧,项目里留存了很多古董玩意儿,既然看到了不爽的地方,身为程序员强烈的责任感,不得不进行改造,今天就来说说统一 Android Theme 中遇到的那些事儿

缘由

我们都知道 Android 系统有很严重的碎片化问题,最明显的表象是手机系统升级大多数不能超过两代,什么意思呢?

简单说就是老机器买来是 5.0 系统,基本升不到 8.0 系统或更高。

可能原因有很多,鄙人也不敢随便揣测,那么过程中呢,出现了各种 AppCompat suppor包, 这些包为开发 app 带来兼容体验,

当然过程中可能发现兼容包有些不可控了,所以现在的主推的是 AndroidX,万剑归宗的感觉。

那么Theme 跟这个碎片化有什么关系呢?

Theme 也经过了几个版本的流行时代,普通 theme 的写法如下

@android:style/Theme.xxx

4.0 之后流行起了 Materail Design,  Android 系统中也默认自带了 theme

@android:style/Theme.Material.xxx

5.0后推出了 appcompat-v7 中的 theme

@style/Theme.AppCompat.xxx

项目中使用的是最普通的 theme,不支持沉浸式,不支持继承自 AppCompatActivity,也会影响部分系统的导航键层级(实测 MUI系统中使用普通 theme 导航键永远处于 window 的最上层)

步骤一:引用整体替换

把 styles.xml 中 parent  引用自 @android:style/Theme.xxx 全部替换为@style/Theme.AppCompat.xxx

这里可以使用as的 ctrl + R 进行快捷全局替换

步骤二:添加MD支持的属性

在base theme中添加如下属性:

<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
  <item name="android:windowNoTitle">true</item>
  <item name="colorPrimary">#ffffff</item>
  <item name="colorPrimaryDark">#ffffff</item>
  <item name="android:statusBarColor">#ffffff</item>
  <item name="android:windowLightStatusBar">true</item>
  <!-- 项目中button不规范使用会造成样式变形,这里把button样式覆盖为最普通的样式,以避免老代码样式走样-->
  <item name="android:buttonStyle">@android:style/Widget.Button</item>
</style>

因为 app 中页面头部皆为白色,所以把状态栏属性改为白色

顺手做了下冷启动的 theme, 设置在 SplashActivity 上

<style name="SplashTheme" parent="AppBaseTheme">
  <item name="android:windowBackground">@drawable/splash_bg</item>
  <item name="android:windowLightStatusBar">false</item>
  <!-- 该属性解决某些系统上layer-list bottom属性看上去失效,实际上是没算上虚拟导航栏的高度 -->
  <item name="android:windowDrawsSystemBarBackgrounds">false</item>
</style>

drawable/splash_bg.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <color android:color="@android:color/white" />
    </item>
    <!-- 
        @dimen/hj_dp_45 是 logo 距离底部的 margin,
        这里把尺寸跟开屏页的 logo 底部 margin 设为一致,
        平滑过渡让用户看上去不会奇怪

        @drawable/splash_logo 是公司 logo
    -->
    <item
        android:bottom="@dimen/hj_dp_45"
        android:gravity="bottom">
        <bitmap
            android:gravity="bottom|center_horizontal"
            android:src="@drawable/splash_logo" />
    </item>
</layer-list>
问题出现与解决

如果不出意外的话,as 已经开始报红色波浪线了,因为styles.xml 中某些属性会有系统兼容的问题,这时候用文件夹兼容方式解决

  • 在 res 下创建文件夹values-v21 及 values-v23
  • -v21 就代表5.0系统会使用该文件夹下的 values 配置
  • -v23 代表6.0系统会使用文件夹下的 values 配置
  • 综上配置,Android 系统会在5.0以下系统选择 values 配置,5.0 - 5.1 选择 values-v21 配置, 6.0+ 会选择values-v23配置

当然这些操作可以用as 中解决问题快捷键 alt + enter 来自动创建对应的样式

这样做了以后,还会出现 5.0系统状态栏白底色把文字颜色混合,导致看不到文字,直接改成黑色:

<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
  <item name="android:windowNoTitle">true</item>
  <item name="colorPrimary">#ffffff</item>
  <item name="colorPrimaryDark">#ffffff</item>

                        喜欢 就关注吧,欢迎投稿!