One of the easiest thing to do with android is storing user preferences. It can be as simple as a single xml files and a few lines of code. Since the first version of Android, you have access to several common preference widgets, such as checkboxes, text fields, or even lists.
In Android ICS, new widgets were introduced, among which the SwitchPreference, looking a lot like the iOS famous SwitchButton. If you have paid attention to the Android Design website, you have noticed that Google encourages you to use a Master On/Off switch in the way they used it with the Wifi Preference screen. Here's a reminder for those of you without an ICS device.
The Wifi can be enabled from the first screen, using the Switch widget. And when you press the Wifi row, you land on the Wifi Preferences screen, where you can select a Wifi Network. At the top of the second screen, you still have a Switch widget to turn the Wifi off if you need to.
Now the question is : how did they do it ? Moreover, how can I do the same in my own preferences ? This is what we're gonna learn in this article. In a fictive video game, here's the preference screens we wan't to see. I'll limit the article to those two screens, others can be done easily after that. This code will only work with API level 14 or higher, so if you're targeting lower devices, be carefull and keep an old fashioned preference screen
For this article, I dug into the source code of Android's Settings application, so most of this is from Google. The probleme can be divided in two parts. First having the Switch widget at the top of the screen in the second screenshot. This is simply done by using a Switch view in the Custom View of the ActionBar. Then, there is the trickier part of having a preference linking to the second screen and having a Switch widget. You can usually have one or the other, using a PreferenceScreen or a SwitchPreference tag in your xml file. Here, we'll use the Header class introduce in ICS, with a custom adapter (basically almost like having a custom ListView, but with predefined behavior).
To create these screens, we need severall files, so instead of copy pasting all the code in here, I bundled a sample project available for download here.
Here's a list of the files you'll find in the archive, and a little description of what they do :
- this file describes the headers of the first screen, meaning each row which links to another PreferenceScreen. Each header can have a title of course, an icon, an id, and a fragment class, defining the PreferenceFragment which will be loaded to display the PreferenceScreen.
- the main PreferenceActivity, which loads first our headers, then will load a fragment when a header is clicked.
- this is the ArraAdapter which will load the Layouts we want for our headers. If you've already worked with ListViews, this should look familiar. This adapter uses 3 different layouts, one for categories sections, one for common header and one for switch header. The "magic" happens in the getHeaderType() method, in which we define which layout should be used with each header.
- this class is mostly a utility we use to bind a Switch widget with the corresponding shared preference. It is linked with the switch defined in the ArrayAdapter described above.
- a PreferenceFragment which is used by our Sound header. Nothing much goes here, we mostly load the PreferenceScreen description from an XML file. Also, as described earlier, we create a Switch widget which we had to the ActionBar, and link it to a SoundEnabler instance.
Now, you have a preference screen with a Switch widget, and what's nice is that this trick can work with any other widget than a switch. You just need to create the layout, add it in the Array Adapter and Voila ! If you have any question on this article, please contact me