29

Now that we have two Icons (Dark and Light) as described in ActionBar Icon Guide.

@drawable/ic_search_light 
@drawable/ic_search_dark

How to reference these Icons in XML menu resource:

<item android:title="Search" android:icon="Which drawable here ? "/>

Every time switch Application theme between Light and Dark, Do I have to update all these drawable references ?

S.D.
  • 29,290
  • 3
  • 79
  • 130
  • Create a Theme for Holo Light and one for Holo dark. Everytime the user picks an other Theme, you can switch between them. – Ahmad Sep 09 '12 at 10:39
  • That doesn't explain how do I reference the menu Icon, This is not a style-able widget. – S.D. Sep 09 '12 at 10:47
  • Actually it does - what I meant was: create 2 Themes/Menus. In the first you can reference all holo light icons, in the second all the holo dark icons. So if your user decides to switch, you just have to change the theme(and not all the icons). – Ahmad Sep 09 '12 at 11:04
  • Updated my findings in the answer. – S.D. Sep 09 '12 at 14:28

1 Answers1

77

There's a way to define android drawables (and many other elements found in res/values) to be Theme dependent.

Lets suppose we have two drawables, menu icons in this case:

res/drawable/ic_search_light.png
res/drawable/ic_search_dark.png

And we want to use ic_search_dark.png for Application theme which is default Theme or extends it, Similarly, we want ic_search_light.png if our Application theme changes to default Theme.Light or some theme extending it.

Define a general attribute with a unique name in /res/attrs.xml like:

<resources>
<attr name="theme_dependent_icon" format="reference"/>
</resources>

This is a global attribute and format type is reference, In case of a Custom View it can be defined along with style-able attributes:

<resources>
    <declare-styleable name="custom_menu">
        <attr name="theme_dependent_icon" format="reference"/>
    </declare-styleable>
</resources>

Next, define two Themes, extending default Theme and Theme.Light (or themes that inherit from these) in res/styles.xml or res/themes.xml:

<resources>
    <style name="CustomTheme" parent="android:Theme">
        <item name="theme_dependent_icon" >@drawable/ic_search_dark</item>
    </style>

    <style name="CustomTheme.Light" parent="android:Theme.Light">
        <item name="theme_dependent_icon" >@drawable/ic_search_light</item>
    </style>
</resources>

Finally, use the reference attribute we define to refer to these icons. In this case, we use while defining a menu layout

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="Menu Item"  android:icon="?attr/theme_dependent_icon"/>
</menu>

?attr refers to an attribute of current theme in use.

Now, we can use above two themes for application:

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

or

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

and corresponding resources will be used accordingly.

Theme can also be applied in Code, by setting it at the very beginning of Activity's onCreate().

UPDATE

Method to access these theme dependent resources from code is explained in this answer.

Community
  • 1
  • 1
S.D.
  • 29,290
  • 3
  • 79
  • 130
  • So goes for all theme dependent resources (pretty much). Good summary. – Rich Ehmer Aug 08 '14 at 18:36
  • 1
    This logic looked over months very weird to me and I've never seen a answer which gave the same short overview as you give with yours. Great explained! Thank you so much. I guess things in xml will get more clear for me, right now. :) – Martin Pfeffer Mar 06 '15 at 06:25
  • Works perfectly for colors as well! – yara Feb 03 '17 at 06:07