关于android:getTheme()。applyStyle(…)多次,而不会覆盖前一个

getTheme().applyStyle(…) multiple times without overwriting the previous one

当我多次将额外属性应用于AppTheme时,它将覆盖前一个属性。 这是我正在使用的代码:

主要活动:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {

    getTheme().applyStyle(R.style.AppTheme_OverlayPrimaryRed);

    // If you change `false` to `true`, the overlay above is overwritten.
    if (false) {
        getTheme().applyStyle(R.style.AppTheme_OverlayAccentRed);
    }

    super.onCreate(savedInstanceState);

    ...
}

AppTheme.OverlayPrimaryRed:

1
2
3
4
<style name="AppTheme.OverlayPrimaryRed">
    <item name="colorPrimary">@color/material_red_500</item>
    <item name="colorPrimaryDark">@color/material_red_700</item>
</style>

AppTheme.OverlayAccentRed:

1
2
3
<style name="AppTheme.OverlayAccentRed">
    <item name="colorAccent">@color/material_red_A200</item>
</style>

有什么想法可以解决这个问题吗?


您的样式定义AppTheme.OverlayPrimaryRedAppTheme.OverlayAccentRed隐式继承自AppTheme。由于AppTheme可能还包含colorPrimarycolorPrimaryDark的定义,因此第二个applyStyle语句也将设置这些属性,从而撤消第一个applyStyle调用。

因此,我在回答此问题时没有在样式覆盖名称中使用任何点。

如果出于美学原因要保留点,则可以为叠加层定义一个空的父样式,如下所示:

1
2
3
4
5
6
7
8
9
10
11
<style name="Overlay">
</style>

<style name="Overlay.PrimaryRed">
    <item name="colorPrimary">@color/material_red_500</item>
    <item name="colorPrimaryDark">@color/material_red_700</item>
</style>

<style name="Overlay.AccentRed">
    <item name="colorAccent">@color/material_red_A200</item>
</style>


编辑2:这是一次失败的尝试,再次应用样式会删除通过编程设置的先前样式。

Android中的每种样式都可以具有父样式。因此,子样式将继承其父样式并也应用自己的样式。此外,孩子可以覆盖其父母的样式或属性。

1
2
3
4
5
6
7
8
9
10
<!-- This is a parent style -->
<style name="AppTheme.OverlayPrimaryRed">
    <item name="colorPrimary">@color/material_red_500</item>
    <item name="colorPrimaryDark">@color/material_red_700</item>
</style>

<!-- This is a child of above style -->
<style name="AppTheme.OverlayAccentRed" parent="AppTheme.OverlayPrimaryRed">
    <item name="colorAccent">@color/material_red_A200</item>
</style>

阅读Android开发者资源中的定义样式。另外,如果您不想使用parent属性:

If you want to inherit from styles that you've defined yourself, you do not have to use the parent attribute. Instead, just prefix the name of the style you want to inherit to the name of your new style, separated by a period. For example, to create a new style that inherits the MyTextStyle style defined, but make the color red, you can author the new style like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style name="MyTextStyle">
    <item name="android:textAllCaps">false</item>
    <item name="android:textColor">#FFFFFF</item>  <!-- white text (default) -->
    <item name="android:textStyle">bold</item>
    <item name="android:textSize">12dp</item>
</style>

<!-- red text -->
<style name="MyTextStyle.RED">
    <item name="android:textColor">#FF0000</item>
</style>

<!-- green text -->
<style name="MyTextStyle.GREEN">
    <item name="android:textColor">#00FF00</item>
</style>

<!-- blue text -->
<style name="MyTextStyle.BLUE">
    <item name="android:textColor">#0000FF</item>
</style>

Notice that there is no parent attribute in the tag, but because the name attribute begins with the MyTextStyle style name (which is a style that you have created), this style inherits all style properties from that style. This style can override the android:textColor property to make the text red. You can reference this new style as @style/MyTextStyle.RED.

You can continue inheriting like this as many times as you'd like, by chaining names with periods. For example, you can extend MyTextStyle.RED to be bigger, with:

1
2
3
<style name="MyTextStyle.RED.Big">
    <item name="android:textSize">30sp</item>
</style>

编辑1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- this is your root style -->
<style name="AppTheme.Overlay">
    <!-- default styles for primary, primaryDark (you can add accent too) -->
</style>

<!-- 1. add Custom Primary Color to root style -->
<style name="AppTheme.Overlay.PrimaryRed">
    <item name="colorPrimary">@color/material_red_500</item>
    <item name="colorPrimaryDark">@color/material_red_700</item>
</style>

<!-- 1. add Custom Accent Color to root style -->    
<style name="AppTheme.Overlay.AccentRed">
    <item name="colorAccent">@color/material_red_A200</item>
</style>

<!-- 2. add Custom Primary Color to root style -->
<style name="AppTheme.Overlay.PrimaryBlue">
    <item name="colorPrimary">@color/material_blue_500</item>
    <item name="colorPrimaryDark">@color/material_blue_700</item>
</style>

<!-- 2. add Custom Accent Color to root style -->    
<style name="AppTheme.Overlay.AccentBlue">
    <item name="colorAccent">@color/material_blue_A200</item>
</style>

<!-- add 10 for each...... -->

为您的原色制作10种样式,为您的强调色制作10种样式。

然后,在您的代码中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// if root style has some styles to add (default)
getTheme().applyStyle(R.style.AppTheme_Overlay);

// first color selection
getTheme().applyStyle(R.style.AppTheme_Overlay_PrimaryRed);
getTheme().applyStyle(R.style.AppTheme_Overlay_AccentRed);

// when you want blue color
getTheme().applyStyle(R.style.AppTheme_Overlay_PrimaryBlue);
getTheme().applyStyle(R.style.AppTheme_Overlay_AccentBlue);

// when you want bluePrimary, but redAccent color (bad choice)
getTheme().applyStyle(R.style.AppTheme_Overlay_PrimaryBlue);
getTheme().applyStyle(R.style.AppTheme_Overlay_AccentRed);

在这里,AppTheme_Overlay_PrimaryBlue将覆盖AppTheme_Overlay_PrimaryRed。等等。

您刚刚添加了一种根样式,十种原色样式和十种强调色样式= 21种样式。