I have an Android app that supports the api 14 and targets api 21. I have some styles that need to be overided by api 21. What happens is that I need to duplicate all style items just to change one item.
For example:
<!-- values/styles.xml -->
<style name="Widget.HelloWorld.Button">
<item name="android:textSize">24sp</item>
<item name="android:drawableLeft">@android:drawable/ic_menu_delete</item>
</style>
If I want to override just the attribute android:textSize
in the api 21 I need to duplicate the item android:drawableLeft
too.
So to avoid this I came to a solution. In this example I have three buttons (foo
, bar
and fancy
) with some styles (Widget.HelloWorld.Button.Foo
, Widget.HelloWorld.Button.Bar
, Widget.HelloWorld.Button.Fancy
)
<!-- values/styles.xml -->
<resources>
<style name="v0.Widget.HelloWorld.Button" parent="Widget.AppCompat.Button">
<item name="android:textSize">24sp</item>
<item name="android:drawableLeft">@android:drawable/ic_menu_delete</item>
</style>
<style name="v0.Widget.HelloWorld.Button.Foo" parent="Widget.HelloWorld.Button">
<item name="android:textColor">#f00</item>
</style>
<style name="v0.Widget.HelloWorld.Button.Bar" parent="Widget.HelloWorld.Button">
<item name="android:textColor">#ff0</item>
</style>
<style name="v0.Widget.HelloWorld.Button.Fancy" parent="Widget.HelloWorld.Button">
<item name="android:textColor">#f0f</item>
</style>
<!-- Alias -->
<style name="Widget.HelloWorld.Button" parent="v0.Widget.HelloWorld.Button" />
<style name="Widget.HelloWorld.Button.Foo" parent="v0.Widget.HelloWorld.Button.Foo" />
<style name="Widget.HelloWorld.Button.Bar" parent="v0.Widget.HelloWorld.Button.Bar" />
<style name="Widget.HelloWorld.Button.Fancy" parent="v0.Widget.HelloWorld.Button.Fancy" />
</resources>
I have prefixed all styles names with the version number of the api that will have impact. Since the values/styles.xml
is the default, i prefixed with v0
.
Now in the values-v21/styles.xml
i can override just the item that i want without duplicating code.
<!-- values-v21/styles.xml -->
<resources>
<style name="v21.Widget.HelloWorld.Button" parent="v0.Widget.HelloWorld.Button">
<item name="android:textSize">36sp</item>
</style>
<style name="v21.Widget.HelloWorld.Button.Fancy" parent="v0.Widget.HelloWorld.Button.Fancy">
<item name="android:colorPrimary">@color/primary</item>
</style>
<!-- Alias -->
<style name="Widget.HelloWorld.Button" parent="v21.Widget.HelloWorld.Button" />
<style name="Widget.HelloWorld.Button.Fancy" parent="v21.Widget.HelloWorld.Button.Fancy" />
</resources>
I want to know what is the cons of this approach.
You can fix the original duplication problem using dimension resources that switch on the version qualifier, then referencing it in the style:
<!-- values/dimens.xml -->
<resource>
<dimen name="hello_text_size">24sp</dimen>
</resource>
<!-- values-v21/dimens.xml -->
<resource>
<dimen name="hello_text_size">36sp</dimen>
</resource>
<!-- values/styles.xml -->
<style name="Widget.HelloWorld.Button">
<item name="android:textSize">@dimen/hello_text_size</item>
<item name="android:drawableLeft">@android:drawable/ic_menu_delete</item>
</style>