In the last episode of “Building ‘Droids”, we covered how to handle a simple, one-criterion choice between two resource sets: whether we show English or Spanish strings. In that case, having two res/ subdirectories (res/values-en/ and res/values-es/), each with their own set of strings, was sufficient.
So, with that in mind, let’s look at situations that are decided more icky…
Where things start to get complicated is when you need to use multiple disparate criteria for your resources. This may come most frequently with layouts, as you might want one layout for portrait and small screens, one layout for larger screens in landscape mode, and variations of each for finger-input versus other types of input (keyboard, stylus). This will allow you to make the best use of the available screen “real estate”, without any coding changes to your activity using the layout.
Once you get into these sorts of situations, though, all sorts of rules come into play, such as:
- The configuration options (e.g., -en) have a particular order of precedence, and they must appear in the directory name in that order. The Android documentation outlines the specific order in which these options can appear. For the purposes of this example, screen orientation must precede touchscreen type, which must precede screen size.
- There can only be one value of each configuration option category per directory. You cannot, for example, consider portrait and square screens to be the same â€” each will require its own named res/layout… folder.
- Options are case sensitive
So, for the scenario described above, in theory, we would need the following directories:
Note that for some of these, the actual layout files will be identical. For example, we only care about finger layouts being different than the other two, but since we cannot combine those two, we would theoretically have to have separate directories with identical contents for no touch and stylus.
Also note that there is nothing preventing you from also having a directory with the unadorned base name (res/layout). In fact, this is probably a good idea, in case future editions of the Android runtime introduce other configuration options you did not consider — having a default layout might make the difference between your application working or failing on that new device.
Now, we can “cheat” a bit, by decoding the rules Android uses for determining which, among a set of candidates, is the “right” resource directory to use:
- First up, Android tosses out ones that are specifically invalid. So, for example, if the screen size of the device is 320×240, the 640×480 directories would be dropped as candidates, since they specifically call for some other size.
- Next, Android counts the number of matches for each folder, and only pays attention to those with the most matches.
- Finally, Android goes in the order of precedence of the options â€” in other words, it goes from left to right in the directory name.
So we could skate by with only the following configurations:
If the device is in portrait or square mode, or does not have a 640×480 screen size, the first two candidates will be skipped, and the layout will be chosen based on whether the device supports finger input or not. Otherwise, one of the two landscape 640×480 layouts will be chosen, as they would be a “stronger” match than the others, with the final determination being on whether the device supports finger input or not.
In our next episode, we’ll start looking at the Android system of Intent objects and see how it effectively gives you a publish/subscribe event bus that your applications can take advantage of.