androidandroid-themeandroid-stylesandroid-attributes

In an attribute's format (and using Color as an example), what is the difference between 'color' and 'color|reference'?


TLDR version

I get why reference is used as the format for attributes which point to default styles when setting up default theming, but how does using reference|color differ from just using color when defining color attributes? You can already use @color/xxx which is already a reference to another resource so is reference implicit? If not, what's the use-case for one over the other?

Full version

I've been following best-practices for theming our application's custom widgets using the following recommended technique.

In attrs.xml

<!-- Attributes holding default styles -->
<attr name="myWidgetStyle"      format="reference" />
<attr name="myOtherWidgetStyle" format="reference" />

<!-- Custom attributes -->
<attr name="indicatorColor" format="color|reference" />

<!-- Assigning attributes to controls -->
<declare-styleable name="MyWidget">
    <item name="android:text" />
    <item name="indicatorColor" />
</declare-styleable>

<declare-styleable name="MyOtherWidget">
    <item name="android:text" />
    <item name="indicatorColor" />
</declare-styleable>

In styles.xml

<style name="ThemeBase">

    <!-- Store default style in the style-reference attributes -->
    <item name="myWidgetStyle">@style/MyWidget</item>
    <item name="myOtherWidgetStyle">@style/MyOtherWidget</item>

    <!-- Reference primaryColor attribute when defining the value for this one -->
    <item name="indicatorColor">?primaryColor</item>
    <!-- alternate: <item name="indicatorColor">?attr/primaryColor</item> -->

</style>

<style name="ThemeA" parent="ThemeBase">
    <item name="primaryColor">@color/primaryColor_themeA</item>
</style>

<style name="ThemeB" parent="ThemeBase">
    <item name="primaryColor">@color/primaryColor_themeB</item>
</style>

Then finally, in the constructors for my widgets, I pass R.attr.myWidgetStyle and R.attr.myOtherWidgetStyle as appropriate to both the call to super as well as to context.obtainStyledAttributes and I can get the defined colors as need. Everything works as expected. My controls are themed appropriately.

However, what I'm wondering is I've sometimes seen this in the attrs.xml file...

<attr name="indicatorColor" format="color" /> <-- Note no 'reference'

and everything still works, leaving me scratching my head on why you would write color|reference instead of just color. I've tried cascading changes through several attributes, defining them in different orders and anything else I could think of to get different results, but they all just work.

So does anyone have an explanation?

Even better, can someone post an example showing different behavior between color and color|reference because as of now, I have yet to find one.


Solution

  • Attribute format is only for the system to know what type of resource this attribute can be.

    color = any color. Hex (#ffffffff) or link to color resource (@color/supa-awesome_color). No @drawable/mega_icon are allowed here

    reference = any reference (@color/supa_awesome_color, @drawable/mega_icon, @string/hi_there, ...)

    color|reference = is an union of the above