Making resources theme dependent

S.D. picture S.D. · Sep 9, 2012 · Viewed 9.3k times · Source

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 ?

Answer

S.D. picture S.D. · Sep 9, 2012

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.