Custom checkboxes for CheckBoxPreferences on Android

For an App I'm writing I need to use custom checkboxes in a PreferenceScreen. I want to use the CheckboxPreferences as it's designed for that. Many searches lead to StackOverflow, but caused me a stack overflow as well as they didn't work. In this (short) post I outline my findings and provide a working solution step by step.

Step 1

You need a custom checkbox. This can be defined in a drawable. In this case I've called the file checkbox.xml and placed it in the drawable folder. The code defines the images for two states: if the checkbox is enabled and when it's disabled. For this file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true"
          android:drawable="@drawable/checkbox_checked" /> <!-- checked -->
    <item android:state_checked="false" 
    	android:drawable="@drawable/checkbox_unchecked" /> <!-- default -->
</selector>

Step 2

We need a layout for customized preferences. This layout defines the same stuff as the ' regular'  preference does (text, summary etc.). Note the last part in the following file (called checkbox_preference.xml and placed in the layout folder). It loads our custom checkbox!

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2006 The Android Open Source Project Licensed under the 
    Apache License, Version 2.0 (the "License"); you may not use this file except 
    in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
    Unless required by applicable law or agreed to in writing, software distributed 
    under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 
    OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
    the specific language governing permissions and limitations under the License. -->

<!-- Layout for a Preference in a PreferenceActivity. The Preference is able 
    to place a specific widget for its particular type in the "widget_frame" 
    layout. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical" android:paddingRight="?android:attr/scrollbarSize">

    <RelativeLayout android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:layout_marginLeft="15dip"
        android:layout_marginRight="6dip" android:layout_marginTop="6dip"
        android:layout_marginBottom="6dip" android:layout_weight="1">

        <TextView android:id="@+android:id/title"
            android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:singleLine="true" android:textAppearance="?android:attr/textAppearanceLarge"
            android:ellipsize="marquee" android:fadingEdge="horizontal" />

        <TextView android:id="@+android:id/summary"
            android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:layout_below="@android:id/title" android:layout_alignLeft="@android:id/title"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:maxLines="4" />

    </RelativeLayout>

<CheckBox android:id="@+android:id/checkbox"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:button="@drawable/checkbox" />

</LinearLayout>

Step 3

Now the code below is the actual layout which you inflate with your SharedPreferences in your Activity. The layout attribute is used to put the custom layout with the custom checkbox as an item in there.

 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

	<PreferenceCategory
		android:title="@string/category_title">
		
	<CheckBoxPreference
	android:key="preferenceKey"
	android:title="@string/preferenceTitle"
	android:defaultValue="false"
	android:layout="@layout/checkbox_preference"
	/>
	</PreferenceCategory>
</PreferenceScreen>

Step 4

There is no step 4. You're done! It shouldn't be that hard to find and use these things. Unfortunately many same questions, but more different (and often not / not completely working replies / solutions) are posed on sites like StackOverflow which makes it harder to find the real solution. Hopefully this post is a worthy addition to the interwebs and a valuable resource for Android designers facing the same problem.

Be Sociable, Share!

9 comments

  1. Donal says:

    One issue I’ve noticed with this is that when you then click on the checkboxpreference it doesn’t work and onClick and onChange listeners don’t work.

    Have you resolved this issue?

  2. Donal says:

    In response to my own question in case anyone comes across it I removed the checkbox in the xml and this worked, the checked was overwriting the actual View underneath, removing it allows the checkboxpreferences own checkbox to display and all works well.

  3. Thanks for posting your solution as well Donal! I had to pull the project where I came across the issue from my version control system, but didn’t have time to do that and look into the issue in such a short term.

    Cheers,

    Patrick

  4. qingu says:

    This almost works great. First off, I agree with the author, that often times on StackOverflow it is hard to find the answers that actually work and usually they are not complete, but piece together previous answers and can only be understood in context.
    Now, of course there are always many solutions to any problem and those depend on the context and of course most stuff out there does not work directly for everyone due to different versions/prerequisites/runtime &c.
    Anyways, the code (if you will call some xml files code) looks good, but to make the buttons work, you have to add two lines in layout/checkbox_preference.xml from above:

    Thanks!

  5. qingu says:

    Hmm… the actual code did not show up in the post. In the CheckBox code add:

    android:focusable=”false”
    android:clickable=”false”

    Good luck!

  6. Antiplod says:

    Thank you gang – worked like a dream!

  7. linus.du says:

    GGGGGGGGGGGGGGGGGGGGGGGGGGreat…..

  8. Keust says:

    Like qingu sad, if you need to implement onClickListener or onSharedPreferenceChanged in your PreferenceActivity you must add
    android:focusable=”false”
    android:clickable=”false”

  9. ssccr says:

    I don’t understand the step 3,can u explain where I put the code? Is it an xml file?

Leave a Reply

Your email address will not be published. Required fields are marked *


− eight = 1