2

I am new to android development, so please bear with me. My app elements (button color, background color, text color, divider color etc.) uses colors from the colors.xml using "@color/mycolor" for example.

My colors.xml looks like:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="mycolor">#202020</color>
    <color name="white">#FFFFFF</color>
    <color name="whitehint">#50FFFFFF</color>
    <color name="primary">#673AB7</color>
    <color name="primary_dark">#512DA8</color>
    <color name="primary_light">#D1C4E9</color>
    <color name="accent">#794cc9</color>
    <color name="primary_text">#212121</color>
    <color name="secondary_text">#a4a4a4</color>
    <color name="icons">#FFFFFF</color>
    <color name="divider">#B6B6B6</color>
</resources>

Now I have a menu where the user can select a different theme which I want to use a second colors2.xml for example which will have the same color names but a different hex code for the keys. How do I go about which xml file does my app references?

  • 1
    This is what color attributes are for. You have multiple themes and let's say that both have defined `something` where *something* is a different color resource (`@color/some_color`) for each of the themes. – Eugen Pechanec May 26 '15 at 23:16
  • @EugenPechanec yes but in there, how do you specify a different colors.xml file? in the line, where do I specify to use colors2.xml in `something` Can you give a small example please? – sudoExclaimationExclaimation May 26 '15 at 23:38

2 Answers2

10
  1. Let's suppose you already know how to switch themes on the fly.
  2. You can have multiple XML files defining colors. colors.xml is just a convention. All these colors will be defined and accessible in parallel...
  3. ...unless you put the file in a different resource bracket. E.g. default colors in res/values/colors.xml and colors for tablets in res/values-sw600dp/colors.xml (the file name is not important) which is probably not what you're going for.

Let's say you have these themes:

<style name="Theme.My.DarkRed" parent="Theme.AppCompat">
    <item name="colorPrimary">#f00</item>
    <item name="colorPrimaryDark">#c00</item>
    <item name="colorAccent">#c90</item>
</style>

<style name="Theme.My.LightBlue" parent="Theme.AppCompat.Light">
    <item name="colorPrimary">#9ff</item>
    <item name="colorPrimaryDark">#6cc</item>
    <item name="colorAccent">#06f</item>
</style>

Now when you define e.g. android:background="?colorAccent" the color appropriate for the theme you're using will be resolved.

Note: Sadly before Lollipop these color attr references could not be used in XML drawables.

How to access color references from outside of XML?

TypedArray a = context.obtainStyledAttributes(new int[]{R.attr.colorPrimary, R.attr.colorAccent});
int colorPrimary = a.getColor(0);
int colorAccent = a.getColor(1);
a.recycle();

What attributes can be specified?

android:windowBackground

android:colorForeground
android:colorBackground

android:textColorPrimary 
android:textColorSecondary

colorPrimary <!-- without prefix in AppCompat, with prefix on pure Lollipop -->
colorPrimaryDark
colorPrimaryAccent
colorControlNormal
colorControlActivated
colorControlHighlight
colorButtonNormal

android:textColorHint
android:textColorLink
android:textColorHighlight

android:listDivider

et cetera, et cetera...

You can look into Android\sdk\platforms\android-*\data\res\values\themes*.xml and appcompat-v7 source for more attributes.

Then you can even define your own attrs (off-topic, use Google).

Eugen Pechanec
  • 37,669
  • 7
  • 103
  • 124
  • absolutely amazing, I want to buy you coffee!! this makes a lot more sense as now I can put the pieces together. thank you!! – sudoExclaimationExclaimation May 27 '15 at 00:17
  • You mentioned "Note: Sadly before Lollipop these color attr references could not be used in XML drawables." How do we achieve this in pre lollipop? all via java code? – sudoExclaimationExclaimation May 29 '15 at 01:49
  • The new `Context.getDrawable(int)` and `Resources.getDrawable(int, Theme)` are used to assign theme attrs to the drawable but these methods aren't present on earlier platforms. I believe a custom drawable inflater would be able to achieve this , but I don't know of any. – Eugen Pechanec May 29 '15 at 09:26
  • Now is better to use ContextCompat.getColor(getActivity(), R.color.colorPrimary) in order to access color – Vaios Aug 29 '18 at 08:43
  • @Vaios Only if you actually define ``. `TypedArray` is used to resolve attibutes defined in the theme (Theme `colorPrimary` may point to `R.color.whatever`.). Don't mix `R.color` and `R.attr`. `ContextCompat.getColor` will not resolve anything but `R.color`. – Eugen Pechanec Aug 29 '18 at 12:07
-1

You should take a look at Styles and Themes. You can set a custom theme to your app in the manifest.

<application android:theme="@style/CustomTheme">

And then when the user selects the menu option to change the theme, you should change the theme programmatically. Take a look at this for dynamically changing the app theme.

Community
  • 1
  • 1
Antrromet
  • 15,294
  • 10
  • 60
  • 75
  • Thanks for replying! I read the doc and tried a quick test. So I have the following in my styles.xml in the values folder: ` ` If I want a text to use red or purple color based on which theme is selected, how do I specify which style to use and change the style? – sudoExclaimationExclaimation May 26 '15 at 23:30