Home » How to create an ImageListPreference

postheadericon How to create an ImageListPreference

The standard android ListPreference does not provide an easy way to display an image for each item if the list. This article describes how you can implement this. The aim is to add the images the same way as the text values are added.

To add the images to the Android ListPreference, we will use a custom xml attribute. To do that we create a new attrs.xml file in the /res/values folder. The file contains this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ImageListPreference">
<attr name="entryImages" format="reference" />
</declare-styleable>
</resources>

ImageListPreference refers to our ListPreference class and will be available within our code as R.stylable.ImageListPreference and entryImages is the name of our custom xml attribute. The format is a reference. Within the /res/xml folder we create a settings.xml file where we define our settings. In this sample just our ImageListPreference.

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cmwmobile="http://schemas.android.com/apk/res/com.cmwmobile.android.samples">

<com.cmwmobile.android.samples.ImageListPreference
android:key="imageList"
android:title="Title"
android:summary="Summary"
android:entries="@array/listNames"
android:entryValues="@array/listValues"
cmwmobile:entryImages="@array/imageValues"/>

</PreferenceScreen>

We define our own schema (cmwmobile) just below where the android schema is defined. Our custom xml attribute is available, now. We add our custom xlm attribute at the bottom of the ImageListPreference declaration. The value is a reference to an array value we will define next.

Within the /res/values/values.xml file we define together with the ListPrefence arrays for entries and entryValues, the array for the images. We use as value a reference to a drawable.

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string-array name="listNames">
<item>"Emo"</item>
<item>"Help"</item>
<item>"Info"</item>
</string-array>
<string-array name="listValues">
<item>"1"</item>
<item>"2"</item>
<item>"3"</item>
</string-array>
<array name="imageValues">
<item>@drawable/ic_menu_emoticons</item>
<item>@drawable/ic_menu_help</item>
<item>@drawable/ic_menu_info_details</item>
</array>
</resources>

The next step is to define the layout of an item within the ImageListPreference. In our case it contains an ImageView and a CheckedTextView. We use a RelativeLayout for the layout. As check mark we use the standard android radio button. See the listing below.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">

<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="6dip" />

 
android:id="@+id/check"
android:checkMark="@android:drawable/btn_radio"
android:layout_width="fill_parent"
android:layout_height="48dip"
android:layout_toRightOf="@id/image"
android:layout_alignParentRight="true"
android:gravity="center_vertical"
android:textColor="@android:color/black"
android:textSize="20dip" />

</RelativeLayout>

Now, we can start coding. We create the ImageListPreference class as a subclass of the android ListPreference. We create a constructor with as arguments the Context and an AttributeSet. This AttributeSet contains our custom xml attribute. The goal within the constructor is to retrieve and store the drawables resource id's. Don't forget to recycle the TypedArray after you are done. After the constructor, we override the onPrepareDialogBuilder(...)method. We need to define the behavior and appearance of our ImageListPreference here. Because of the custom layout we use a ArrayAdapter to handle the creation of the view of each row. As final statement we call the super.onPrepareDialogBuilder(...). We create maximum reuse of the default ListPreference behavior and layout.

Finally, we create the ImageArrayAdapter as a subclass of the ArrayAdapter. We override the getView(...) method to apply our custom layout. We need to use a LayoutInflater to load and inflate the custom layout. We assign the image to the ImageView and the text to the CheckedTextView. We have to set the previous checked item within this method. I couldn't find a way to let the base class do it. And that's it. Some sanity checks should be added to validate the length of the image list for example. The full source code with a working sample can be downloaded below and is created for Android 2.1 and above. Have fun and don't forget to like, plus or retweet if you like this blog.

The ImageListPreference is used within the following apps:
Lissajous Live Wallpaper

Attachments:
Download this file (SampleImageListPreference.zip)SampleImageListPreference.zip27 Kb