规则总结
| 情况 | 合并结果 |
|---|---|
相同 name 的 <style> |
以优先级高的为准 ,不会合并内部 <item>,完全覆盖! |
相同的 <item> 属性 |
如果 style 被覆盖,内部所有 item 都跟着被覆盖。 |
不同的 <item> 属性 |
如果 style 没有被覆盖 ,则两个文件中的 item 会合并。 |
优先级顺序(从高到低)
-
Build Type 资源 (如
src/debug/) -
Flavor 资源 (如
src/yourFlavor/)← 你的分支文件夹在这里 -
主资源 (
src/main/res/) -
依赖库资源(AAR/JAR)
具体示例
假设你有两个文件:
主目录 src/main/res/values/styles.xml:
xml
<style name="AppTheme" parent="Theme.AppCompat">
<item name="colorPrimary">#FF0000</item>
<item name="colorAccent">#00FF00</item>
</style>
分支目录 src/yourFlavor/res/values/styles.xml:
xml
<style name="AppTheme" parent="Theme.AppCompat">
<item name="colorPrimary">#0000FF</item>
</style>
最终结果:
xml
<style name="AppTheme" parent="Theme.AppCompat">
<item name="colorPrimary">#0000FF</item>
<!-- colorAccent 消失了!因为整个 style 被覆盖了 -->
</style>
⚠️ 关键点 :分支中的
AppTheme完全覆盖 了主目录的AppTheme,而不是合并。如果你希望保留主目录的其他属性,必须在分支的styles.xml中重新声明所有需要的<item>。
如何避免覆盖问题?
方案一:使用不同的父主题
分支中的 style 继承自主目录的 style,这样主目录的属性会自动继承:
xml
<!-- 分支 styles.xml -->
<style name="AppTheme" parent="BaseAppTheme">
<!-- 只写需要覆盖/新增的属性 -->
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@style/ScaleAnimation</item>
</style>
方案二:完全独立定义
如果你的定制变化很大,直接定义一个完全独立的主题名:
xml
<!-- 分支 styles.xml -->
<style name="AppTheme.Special" parent="Theme.AppCompat">
<!-- 完全独立的定义 -->
</style>
然后在 AndroidManifest.xml 中根据分支动态指定(通过 Manifest 占位符或 Gradle 脚本)。