解决修改 Style Attributes 不起作用的问题

今天新建一个项目时遇到了一个问题,项目中大部分 Activity theme 需要显示 ActionBar,个别页面根据业务不需要显示。
需求很简单,直接定义 AppTheme 作为 Application 的基础样式,再定义一个子样式 AppTheme.NoTitle,修改为无 ActionBar 即可。

问题代码

AndroidManifest.xml 部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.coustom.coustom">
<application
android:theme="@style/AppTheme">
<activity
android:name=".CoustomActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoTitle" />
</application>
</manifest>

values/styles.xml 部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/color_primary</item>
<item name="colorPrimaryDark">@color/color_primary_dark</item>
<item name="colorAccent">@color/color_accent</item>
...
</style>
<style name="AppTheme.NoTitle">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>

运行结果依旧显示 ActionBar,怀疑在 BaseActivity 中做了多余的事情,但排查下来并没有找,并且在以往的项目中也是可以成功Work的。

原因

再排除了一些列可能的原因后,终于找到了问题原因:

在修改 Style Resource 的属性的格式为:

1
<item name="[package:]style_property_name">style_value</item>

[package:] is the name of the package in which the resource is located (not required when referencing resources from your own package).
[package:] 用于指定属性所在的包名,属性在当前包下时则无需添加。

若添加在属性名称前添加 andoird: 时即指定属性为 android 包下。

而项目的 Base Style AppTheme 继承自 Theme.AppCompat,位于 appcompat-v7 library, 而不是 android 包下。
所以错误地使用 android:windowActionBarandroid:windowNoTitle,应该使用 windowActionBarwindowNoTitle。将代码修改为:

修改后的代码

values/styles.xml 修改后的部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/color_primary</item>
<item name="colorPrimaryDark">@color/color_primary_dark</item>
<item name="colorAccent">@color/color_accent</item>
...
</style>
<style name="AppTheme.NoTitle">
<!--<item name="android:windowActionBar">false</item>-->
<!--<item name="android:windowNoTitle">true</item>-->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
</resources>

在之前的项目中,Base Style 继承自 @android:style/Theme.Holo.Light,故使用修改前的代码是没有问题的。

总结

修改 Style attributes 时候

  • Parent Style 来自 @android:xxx 时,在属性名前添加 android:
    例如 <item name="android:windowActionBar">false</item>
  • Parent Style 不来自@android:xxx 时,无需在属性名前添加 android:
    例如 <item name="windowActionBar">false</item>

参考链接

what’s the difference between windowActionBar and android:windowActionBar
Accessing Resources | Android Developers
Style Resource | Android Developers