getTheme()。applyStyle(...)多次而不覆盖前一个

时间:2017-01-21 13:15:13

标签: android android-activity android-xml android-theme android-styles

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

MainActivity:

@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:

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

AppTheme.OverlayAccentRed:

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

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

3 个答案:

答案 0 :(得分:2)

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

因此我在this question的答案中没有在样式叠加名称中使用任何点。

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

<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>

答案 1 :(得分:1)

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

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

<!-- 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开发者资源中阅读Defining Styles。另外,如果您不想使用parent属性:

  

如果要继承自己定义的样式,则不必使用parent属性。相反,只需将要继承的样式的名称添加到新样式的名称前面,并用句点分隔。例如,要创建一个继承了定义的MyTextStyle样式但是将颜色设置为红色的新样式,您可以创建这样的新样式:

<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>
  

请注意,标记中没有父属性,但由于name属性以MyTextStyle样式名称(您创建的样式)开头,因此该样式会继承该样式的所有样式属性。此样式可以覆盖android:textColor属性以使文本变为红色。您可以将此新样式引用为@style/MyTextStyle.RED

     

通过将名称与句点链接,您可以像您一样多次继续这样的继承。例如,您可以将MyTextStyle.RED扩展为更大,使用:

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

修改1:

<!-- 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种样式。

然后,在您的代码中:

// 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种样式。

答案 2 :(得分:0)

应用了样式

case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hWnd, &ps);

    // For the moment, I'm just hard-coding a fairly bright red fill:
    HBRUSH brush = CreateSolidBrush(RGB(192, 0, 0));
    HBRUSH original = (HBRUSH)SelectObject(hdc, brush);

    // TODO: Add any drawing code that uses hdc here...
    for (auto& rc : vRect)
    {
        Rectangle(hdc,
            rc.left,
            rc.top,
            rc.right,
            rc.bottom
        );
    }
    // restore original brush before releasing the DC:
    SelectObject(hdc, original);
    EndPaint(hWnd, &ps);

    // And destroy the brush:
    DeleteObject(brush);
}
break;

在活动销毁之前保存样式:

textInputStyle = R.style.TextInputFilled;
recreate();

在创建活动时应用样式:

@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("textInputStyle", textInputStyle);
}