【问题标题】:change colours in styles.xml that are set in colors.xml更改在 colors.xml 中设置的 styles.xml 中的颜色
【发布时间】:2019-07-31 18:44:53
【问题描述】:

我在我的 colors.xml 中设置了自定义颜色,如下所示,但是,是否可以如下更改/更新我的 styles.xml 主题节点中的颜色;

colors.xml

<resources>
    <color name="themeBackground">#000000</color>
    <color name="darkColor">#000000</color>
    <color name="lightColor">#ffffff</color>
<resources>

并在我的 v21\styles.xml 中手动更改,如下所示

//used in activity
onCreate().setTheme(R.style.DarkTheme);

v21\styles.xml

<style name="DarkTheme">
    <!-- change themeBackground manually here -->
    <item name="themeBackground">@color/darkColor</item>
</style>

<style name="LightTheme">
    <!-- change themeBackground manually here -->
    <item name="themeBackground">@color/lightColor</item>
</style>

我已经尝试过了,但没有运气,因为似乎只能更改 android 值,即

<item name="colorPrimary">@color/lightColor</item>

【问题讨论】:

  • 所以,您需要动态主题。对吗?
  • 你可以这么说,但只是认为这可能是最简单的选择,方法是设置额外的默认自定义颜色,然后按 setTheme();recreate(); ..而不是通过我还没有尝试过的 theme.xml 做更长的路...
  • 根据medium.com/@vinitagrawal91/…通过theme.xml
  • XML 样式是不可变的。您不能即时更改它们。在 setTheme 之后你可以调用 activity.recreate() 来查看效果。 onCreate().setTheme(R.style.DarkTheme);不起作用。
  • 是的,但自定义颜色更改在多个

标签: java android xml colors styles


【解决方案1】:

使用 values\themes.xmlvalues\attrs.xml em> + values\colors.xml

*Ensure any themes created in values\styles.xml are not duplicated in themes.xml (i.e same key name &lt;style name="LightLoginThemeV3"&gt;)*

在下面添加到 values\colors.xml (应该已经存在...)

<!-- light Theme colors -->
<color name="lightBackgroundPrimaryV3">@color/white</color>
<color name="lightBackgroundSecondaryV3">@color/lighter_grey</color>
<color name="lightBackgroundAltV3">@color/lighter_grey</color>
<color name="lightBackgroundAltAlphaV3">#809E9E9E</color>
<color name="lightBackgroundLightV3">#80FFFFFF</color>
<color name="lightThemePrimaryColourV3">#01aac4</color>
<color name="lightThemeSecondaryColourV3">#025f8b</color>
<color name="lightThemeDarkPrimaryColourV3">@color/white</color>
<color name="lightThemeDarkSecondaryColourV3">@color/lighter_grey</color>

<!-- dark Theme colors -->
<color name="darkBackgroundPrimaryV3">#241e45</color>
<color name="darkBackgroundSecondaryV3">#2f2856</color>
<color name="darkBackgroundAltV3">#483e81</color>
<color name="darkBackgroundAltAlphaV3">#80483e81</color>
<color name="darkBackgroundLightV3">#f4f3f3</color>
<color name="darkThemePrimaryColourV3">#01aac4</color>
<color name="darkThemeSecondaryColourV3">#025f8b</color>
<color name="darkThemeDarkPrimaryColourV3">#2f2856</color>
<color name="darkThemeDarkSecondaryColourV3">#50448f</color>

values\attrs.xml (如果不存在,则在 values 文件夹中创建 attrs.xml)

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- background color keys -->
    <attr name="basePrimaryBackgroundColour" format="reference|color"/>
    <attr name="baseSecondaryBackgroundColour" format="reference|color"/>

</resources>

values\themes.xml (如果不存在,则在 values 文件夹中创建 attrs.xml)

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="LightLoginThemeV3">

        <!-- keys from values/attrs.xml file -->
        <!-- background color keys -->
        <!-- using light Theme colors via @color -->
        <item name="basePrimaryBackgroundColour">@color/lightBackgroundPrimaryV3</item>
        <item name="baseSecondaryBackgroundColour">@color/lightBackgroundSecondaryV3</item>

        <item name="windowNoTitle">true</item>
        <!-- Support library compatibility -->
        <item name="windowActionBar">false</item>
        <item name="android:windowBackground">@color/backgroundSecondaryV3</item>
        <item name="android:popupBackground">@color/backgroundSecondaryV3</item>

        <!-- EditText Fields -->
        <item name="colorControlNormal">@color/medium_grey</item>
        <item name="colorControlActivated">@color/themePrimaryColourV3</item>
        <item name="colorControlHighlight">@color/themePrimaryColourV3</item>

    </style>

    <style name="DarkLoginThemeV3">

        <!-- keys from values/attrs.xml file -->
        <!-- background color keys -->
        <!-- using dark Theme colors via @color -->
        <item name="basePrimaryBackgroundColour">@color/darkBackgroundPrimaryV3</item>
        <item name="baseSecondaryBackgroundColour">@color/darkBackgroundSecondaryV3</item>

        <item name="android:windowNoTitle">true</item>
        <!-- Support library compatibility -->
        <item name="windowActionBar">false</item>
        <item name="android:windowBackground">@color/colorTrans</item>
        <item name="android:popupBackground">@color/darkist_grey</item>

        <!-- EditText Fields -->
        <item name="colorControlNormal">@color/dark_grey</item>
        <item name="colorControlActivated">@color/colorPrimary</item>
        <item name="colorControlHighlight">@color/colorPrimary</item>

    </style>

</resources>

在我的相关布局文件中,像这样设置背景...

 //key from values/attrs.xml file
 android:background="?attr/basePrimaryBackgroundColour"

在我的活动 onCreate() 方法(和 onResume() 方法)中,通过下面的动态从 values\themes.xml 设置主题...

if(darkTheme){
    setTheme(R.style.DarkLoginThemeV3);
}else{
    setTheme(R.style.LightLoginThemeV3);
}

在我的活动中,通过 clickListner 事件,通过下面的动态从 values\themes.xml 更改主题...

if(darkTheme){
    setTheme(R.style.DarkLoginThemeV3);
    recreate();
}else{
    setTheme(R.style.LightLoginThemeV3);
    recreate();
}

【讨论】:

    【解决方案2】:

    有多种方法可以在运行时应用主题。其中之一已被很好地覆盖here。这些方法的问题是您必须通过调用recreate() 至少重新创建一个活动。但是您可能会遇到重新创建活动不可行的情况,这可能是由于它对数据的依赖或现有架构模式的低效率。

    还有一些其他方法也可以在不重新创建活动的情况下工作:递归查找视图和应用主题。为了能够做到这一点,第一个约束是拥有所有自定义视图。

    对于每个框架视图或视图组,定义自定义视图,如下例所示:

    class CustomTextView extends AppCompatTextView {}
    

    现在您将需要一个类似于下面示例的界面,该界面可以在视图中实现并在动态更改主题时触发。

    interface Painter {
      void applyTheme(int theme)
    }
    

    在您的自定义视图类中实现,如下所示:

    class CustomTextView extends AppCompatTextView implements Painter {
         @Override
         public void applyTheme(int theme) {
              switch (theme) { ... }
         }
    }
    

    在您的活动中,递归地找到实现Painter 并触发applyTheme 的视图,如下所示:

    public void onChangeThemeClick(int selectedTheme){
         View rootView = findViewById(android.R.id.content);
         paintRecurively(rootView,selectedTheme);
    }
    
    public void paintRecurively(View view, int theme) {
       //if view implements painter, trigger the method
       if(view instanceof Painter){
         (Painter)view.applyTheme(theme);
       }
       //if view is viewgroup then further call this method for its children.
       if(view instanceof ViewGroup){
          ViewGroup vg = (ViewGroup)view;
          for(...childCount of vg){
              paintRecurively(vg.getChildAt(i),theme);
          }
       }
    
    }
    

    这听起来可能需要做很多工作。但是,只有在您不想重新创建活动时才需要这样做。

    【讨论】:

    • 如您所说,非常了解 recreate() 方法及其限制。
    • 好的。我认为将两种方式都保留在这里以供参考会很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多