MultiChoice Preference Widget for Android


Strangely, the Android framework does not include a widget which allows multiple selections in Preference Screens. I needed to add one of these for selecting folders to monitor for new media in PicPush and ended up having to implement it myself. If this is something you need for your Android app, following this tutorial will have you up and running in under 5 minutes.

Step 1: Declare a multi-choice preference widget in XML

The first step involves adding the appropriate XML to the file where your preference screen is defined. This can be done as so (You’ll have to change the undefined references to @string constants):

            <com.threefiftynice.android.preference.ListPreferenceMultiSelect android:defaultValue="#ALL#"
                android:dependency="@string/pref_auto_scan_image"
                android:key="@string/pref_upload_buckets_image"
                android:title="Image folders to monitor" android:dialogTitle="Image folders to monitor"
                android:summary="Specify which folders should be monitored for images"
                android:entries="@array/pref_upload_buckets_default_entries"
                android:entryValues="@array/pref_upload_buckets_default_values"/>

Step 2: Create Java class which implements the Multiple Choice List Preference

Now, of course, we need a Java class to back this up. The implementation is straightforward. It extends the ListPreference widget so it can inherit all the XML attributes recognized by it. From there, a few key methods are overridden. Source code can be downloaded from here.

Step 2.1: Override onPrepareDialogBuilder (line 44)

onPrepareDialogBuilder is the method responsible for creating the popup dialog which contains all the choices to be displayed. The change from the base class here is simply to set the multi choice entries of the builder rather than the single choice entries. This takes care of the UI.

Step 2.2: Override onDialogClosed (line 69)

When the dialog is closed we need to build a special string to store in the SharedPreferences. The string is made up of the selected entries separated by a special separator string. The separator string i chose is quite weird, it has to be, to avoid conflicts with actual entries.

Step 2.3: Provide a static convenience method for parsing the stored value into a String array (line 62)

When a client reads back the stored value from the SharedPreferences it wont be very useful unless it can be parsed. This can be delegated to our custom implementation via a static method called parseStoredValue. This convenience method returns a String array which contains the user’s choices.

Step 3: You’re Done! Run the code!

Following the above steps should have you in good shape to get up and running. I implemented this code a few days ago, and am writing this tutorial from memory so i may have missed a few small details, however the main bones of the implementation is definitely contained here. Any problems/questions? Leave a comment below.

Walla!

Walla!

, , , ,

  1. #1 by Steve M at October 11th, 2009

    I am very novice at java and android.
    I got the menu to appear and allow multiple selections. My question is how can I get access to the stored string[] array.
    I also want to say thank you for this.

  2. #2 by declanshanaghy at January 24th, 2010

    Sorry for the huge delay on getting back to you here.
    The choices are stored in the preferences as a plain old string so read it back using something like this:

    String rawval = prefs.getStirng(KEY)
    String[] selected = ListPreferenceMultiSelect.parseStoredValue(rawval);

  3. #3 by cash advances online at April 20th, 2010

    I took java classes a few years ago and am currently pretty new using android. I am going to try this. Thanks for posting this by the way. But hopefully it will all go smooth.

  4. #4 by Peter at June 19th, 2010

    I have run into a few problems using this code on my HTC Desire.
    The ListPreference onSetInitialValue and setValue implementations are both throwing

    java.lang.ClassCastException: java.lang.Boolean

    Is there an updated version for 2.1?

  5. #5 by Santosh at June 24th, 2010

    Excellent! Thanks for publishing this.

  6. #6 by JRS at July 14th, 2010

    Hi, I’m new to java myself and have a (probably) dumb question.

    In your XML:
    android:entries=”@array/pref_upload_buckets_default_entries” android:entryValues=”@array/pref_upload_buckets_default_values”/>

    where is “pref_upload_buckets_default_entries” actually defined?

    Thanks!

  7. #7 by declanshanaghy at July 14th, 2010

    @array/pref_upload_buckets_default_entries referrs to an array defined in res/values/arrays.xml

    In this array you should put the entries that you want to display on the dialog with checkboxes.

    @array/pref_upload_buckets_default_values defines the values that co-respond to each of the entries.

    P.S.
    The names pref_upload_buckets_* are application specific, you should name you arrays accordingly for your application

  8. #8 by JRS at July 14th, 2010

    OK, thanks. I am trying to build my array list from a list of folders gained through the java code by looking at the SDCard. Stuck on that, but thank you for the quick reply!

    I just don’t know how to pass the array list from java to the listpreference.

  9. #9 by JRS at July 15th, 2010

    Banging my head against a will with this, do you happen to have a short example showing how to populate the initial list and states of the checked boxes from java? Would really be appreciated.

    Thank You!

  10. #10 by declanshanaghy at July 15th, 2010

    I tried to email you an example but it seems the emial address you put in is not valid.

    Please email me: declan@350nice.com

  11. #11 by Leimi at August 3rd, 2010

    Hey, thanks a lot for this :)
    I’d like to know, is there a way to put multiple elements in the “android:DefaultValue” xml attribute so that multiple items are checked by default ?
    Thanks,
    Leimi

  12. #12 by Leimi at August 11th, 2010

    Answering myself :
    In fact we can just put one string containing the values we want separated by the separator from the ListPreferenceMultiSelect.
    For example if I want 50, 80 and 90 selected by default and my separator is “xxx” I will just put :
    android:DefaultValue=”50xxx80xxx90″
    in the xml !
    After that, in the Java code, we use the :
    ListPreferenceMultiSelect.parseStoredValue()
    method !

  13. #13 by Nick at August 24th, 2010

    Curious how you might implement a max selection on the # of checkboxes allowed in this multicheckbox dialog? I can’t quite figure out how to do it. I can determine how many are checked, and ensure that any new checked boxes are not saved, but how do I override the check mark icon from appearing at all. Any thoughts from the poster or others would be appreciated:)

  14. #14 by declanshanaghy at August 25th, 2010

    You would have to override how the dialog is constructed, replacing it with an Adapter that attaches an onClickListener to the checkboxes (to get click events) or in the getView method find the checkbox and hide/disable it as required.

    Tricky but with some poking around i think it could be done.

  15. #15 by pengwang at August 28th, 2010

    i donot appear “all” in the dialog as you like,
    in my array.xml i used

    Alpha Option 01
    Beta Option 02
    Charlie Option 03

    so my dialog only appear three items,donot appear “all ” on the top .why?

(will not be published)
  1. No trackbacks yet.