jnovacho jnovacho - 2 months ago 17
Android Question

How to use Android styles inheritance with different qualifiers

I'm working on Android app and I have to support API 19 and higher. So my styles structure looks like this:

res
values
styles.xml
values-v21
styles.xml


In
styles.xml
I have

<style name="customButton" parent="Base.Widget.AppCompat.Button">
<item name="android:focusable">false</item>
<item name="android:clickable">true</item>
</style>


and in the
v21/styles.xml
I have

<style name="customButton" parent="customButton">
<item name="android:elevation">10dp</item>
</style>


While this works, it doesn't seem right. And the Android studio is complaining about cyclic references. That is because the
v21/customButton
has technically itself as a parent.

I cannot rename the
v21/customButton
to
customButton21
because then I would have to create two versions of everything that uses this style. While only difference is the new attribute added in API 21.

What is the correct way to solve this issue? Maybe create
base-style.xml
and then reference it in specific API styles?

PS: This question applies to any qualifiers, not only the API.

Answer

I have settled for following solution:

attrs.xml

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

values/styles.xml

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="@attr/buttonStyle">@style/buttonStyleBase</item>
    </style>

    <style name="buttonStyleBase">
        <item name="android:gravity">left</item>
        <item name="android:textSize">20sp</item>
    </style>
</resources>

values-v21/styles.xml

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="@attr/buttonStyle">@style/buttonStyle21</item>
    </style>

    <style name="buttonStyle21" parent="buttonStyleBase">
        <item name="android:elevation">15dp</item>
    </style>
</resources>

And then to use it:

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        style="?attr/buttonStyle" />

This way I can inherit the base style which can be as complex as I need and apply only changes that are relevant to another SDK version.