Tuesday, August 2, 2011

New to Android: More Style Restrictions

There have been two changes the Android platform build tools which have caught me off guard. You may run into these problems when you next update your aapt. Both of them cause compilation errors, so they're not easy to ignore, but it's not immediately obvious how to fix either.

Change #1: Implicit parenting now requires a parent

Suppose I have this style defined in styles.xml:

<style name="Widget.MyWidget.Small"> ... </style>

It was named that way after how Android sets up their widget styles (for example, "Widget.RatingBar.Small"). One thing to know is the implicit aspects to using dots in the naming is that you automatically parent all the styles before the dot. So "Widget" is the parent of "Widget.MyWidget", and "Widget.MyWidget" is the parent of "Widget.MyWidget.Small".

In the new version of aapt, you'll see this error:

Error retrieving parent for item: No resource found that matches the given name '@Style/Widget.MyWidget'.

This happens now because aapt is stricter with regards to style parenting. Before, if there was no parent, it would just ignore this oversight; now it requires a parent.

There are two possible solutions:

1. Rename the style so that it doesn't use implicit parenting with dots.

2. Create the parent styles. They could either be empty, or you could actually use them for something.

I think #1 makes more sense, unless you actually have a use for the parent styles.

Change #2: Some android styles are now enforced as private

Before, you used to be able to get away with parenting some non-public Android styles:

<style name="MyRatingBar" parent="@android:style/Widget.RatingBar.Small"> ... </style>

However, these styles have always been intended to be private, and the latest aapt will not allow you to build with a private parent defined. A Google employee explained the reason why this is no longer allowed:

For the framework, only public resources are guaranteed to only have the same integer, build after build. The integer of private resources integer will change from build to build. This means that your custom style is referencing a parent that *will not* be valid once installed on a device. It'll referenced either another resources or none at all, and it won't do what you want.


That seems reasonable to me. The solution is to just import the entire style into your styles.xml; all the styles are open source anyways.