Fun With Density Resource Set Qualifiers

The normal rule for resource set qualifiers, like -large or -land, is that only those that match the device’s current configuration will be used. One oft-mentioned exception to this rule are density resource set qualifiers, like -hdpi and -xxhdpi, where Android will choose from another “near” resource set if there is no exact match.

This latter capability was always described in the context of drawable resources, where Android has the ability to “convert” a resource from one set to another, such as downsampling an image. Therefore, I had assumed that this resource set trickery was a feature of drawable resources.

It’s not.

It’s a feature of the density resource set qualifiers.

(probably many of you already realized this, or guessed better than I did)

So, for example, if you have an app with res/values/strings.xml and res/values-xxhdpi/strings.xml, and you request a string resource on an -xhdpi device, my assumption was that you would get the one from res/values/strings.xml. After all, you do not match the density, and Android cannot really convert a string between densities, so you would get the default. In reality, at least on Android 4.2, you get the one from res/values-xxhdpi/strings.xml. Android applies the same rules for choosing a resource set based on density for strings as it does drawables.

Now, in truth, you should not run into this very often. Outside of maybe some game apps, having layouts or menus or preferences that vary by screen density is a strong code smell. But if you are tweaking dimension resources using density resource sets (for cases where the straight-up dp conversions do not quite give you what you want), or similar situations, just bear in mind that all resources, not just drawables, are affected by the way density resource set qualifiers are used.

Many thanks to Morrison Chang, whose answer and comments on StackOverflow triggered my research in this area.