20

I'm pretty sure that this question already has been answered somewhere. It just seems too common. But I can't find the answer. I can't also figure out the solution.

Here's the problem:

I want one of my TableRow's to have different background color. It's simple, I just need to add

android:background="#123456" 

In TableRow's XML Declaration. But, I also want my application to have two themes. In the other theme, the TableRow should have different background color. I just can't find a way to define a color value inside a theme and use it. I would like to type something like this:

<style name="Theme.MyApp" parent="@style/Theme.Light">
   <color "my_cool_color">#123456</color>
</style>

<style name="Theme.MyApp.Dark" parent="@style/Theme.Dark">
   <color "my_cool_color">#654321</color>
</style>

And, in TableRow's declaration:

android:background="@color/my_cool_color"

So, when I change the theme, the color of that one TableRow's background also changes. I've tried in many ways for many hours and didn't succeed... One thing I didn't try, was creating my own widget basing on TableRow and declaring a separate style for it - I think this should work, but it's just too heavy solution for so simple problem.

user1234567
  • 1,832
  • 1
  • 18
  • 25

1 Answers1

54

You can do this using attributes. First define your attribute in attrs.xml (this file goes under the 'values' folder):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="myCoolColor" format="color" />
</resources>

Then in your styles.xml, define myCoolColor for each theme:

<style name="Theme.MyApp" parent="@style/Theme.Light">
   <item name="myCoolColor">#123456</item>
</style>

<style name="Theme.MyApp.Dark" parent="@style/Theme.Dark">
   <item name="myCoolColor">#654321</item>
</style>

Now, specify myCoolColor as the background of your view:

android:background="?myCoolColor"

You can go further and use a reference to a color so you can keep your colors defined in one place. Change the attribute to include a reference (note that we can use a color OR a reference):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="myCoolColor" format="color|reference" />
</resources>

Change your styles.xml to reference a color for each theme:

<style name="Theme.MyApp" parent="@style/Theme.Light">
   <item name="myCoolColor">@color/blue</item>
</style>

<style name="Theme.MyApp.Dark" parent="@style/Theme.Dark">
   <item name="myCoolColor">@color/green</item>
</style>

Finally define the colors in your colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="blue">#0000FF</color>
    <color name="green">#00FF00</color>
</resources>

That's it!

aromero
  • 25,681
  • 6
  • 57
  • 79
  • Thanks! I found something about attr.xml, but couldn't find a suitable example. On the contrary, your answer couldn't be more complete! – user1234567 Dec 26 '11 at 00:21
  • I found your answer very useful, and solved my problem also. +1. But I still have one problem, I want to use the defined colors in code. How can I do that, how to use the colors from attrs in code (not xml)? – Sandra Apr 12 '13 at 13:40
  • Yes, but if I use the dark theme I want the color to be blue, and for the other green. But how can I get the right color in code? – Sandra Apr 12 '13 at 14:05
  • 4
    Ok, I found a solution. int[] attrs = new int[] { R.attr.myCoolColor}; TypedArray ta = context.obtainStyledAttributes(attrs); int appColor = ta.getColor(0, 0); ta.recycle(); Hope this helps for someone that has same problem. – Sandra Apr 12 '13 at 14:30
  • 1
    If you want to use that color attribute now, use `android:background="?attr/myCoolColor"`. – lenooh Jan 29 '16 at 00:03