Web Development

Create a custom checkbox in your Android app

When dealing with a checkbox in Android, a custom selector is assigned to the button property. This is important to know before following this Android tutorial.

Like all widgets that come with the Android UI kit, the standard checkbox can be customized -- you can control the colors, behavior, and even the shape. The approach should be familiar if you've done any UI skinning with the platform: add your graphic resources for the checked and unchecked states, create an XML selector, and assign your selector to the checkbox in your layout.

Except last week when I actually needed a custom checkbox in an application I was doing for a client, it didn't seem to work. (Don't you hate when that happens?) Pressed for time, I double and triple checked my state selector and everything seemed copasetic. Some days I just hate computers!

After about an hour of pulling my hair out, I found the error of my ways. I had assumed that, like all the other widgets I've dealt with on the platform, the custom selector was assigned to the background property. In fact, when dealing with a checkbox, a custom selector gets assigned to the button property.

This tutorial is a quick run-through for creating a custom checkbox. You can follow along step by step, or download and import the source code.

1. Open Eclipse and start a new Android project. Target Android 1.6 or higher. Be sure to rename the startup activity to Main.java.

2. Create a folder called /xml in the /res directory.

3. Add three XML-based resources to the /res/xml folder, two that represent the drawing code for the actual checkbox and a third that is the state selector.

checked.xml

<?xml version="1.0" encoding="UTF-8"?>

<shape xmlns:android=http://schemas.android.com/apk/res/android

android:shape="rectangle">

<gradient android:startColor="#ffff0000" android:endColor="#ff000000" android:angle="270"/>

<stroke android:width="4px" android:color="#ffc0c0c0" />

<size android:height="20dp" android:width="20dp"/>

</shape>
Unchecked.xml

<?xml version="1.0" encoding="UTF-8"?>

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

android:shape="rectangle">

<gradient android:startColor="#ff585858" android:endColor="#ff000000" android:angle="270"/>

<stroke android:width="4px" android:color="#ffc0c0c0" />

<size android:height="20dp" android:width="20dp"/>

</shape>

custom_checkbox.xml

<?xml version="1.0" encoding="utf-8"?>

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

<item android:state_checked="true"

android:drawable="@xml/checked" />

<item android:state_pressed="true"

android:drawable="@xml/checked" />

<item android:drawable="@xml/unchecked" />

</selector>

4. Define this activity's layout in the /res/layout folder. The layout runs a tad long, but it is nothing more than a series of horizontal and vertical layouts that contain a couple of checkboxes and labels to go along with the checkboxes. In main.xml, you don't want to miss the assignment of the custom checkbox selector. This is where common sense and experience will bite you if you're not careful.

main.xml

<?xml version="1.0" encoding="utf-8"?>

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

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical" >

<TextView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textSize="20dip"

android:gravity="center"

android:padding="10dip"

android:text="Check It!" />

<TextView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textSize="16dip"

android:gravity="center"

android:padding="10dip"

android:text="Here is a checkbox..." />

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:gravity="center"

android:orientation="horizontal">

<CheckBox

android:id="@+id/checkbox1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:button="@xml/custom_checkbox"/>

<TextView

android:id="@+id/textview1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textSize="14dip"

android:gravity="center"

android:padding="10dip"

android:text="(unchecked)" />

</LinearLayout>

<TextView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textSize="16dip"

android:gravity="center"

android:padding="10dip"

android:text="And here is another..." />

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:gravity="center"

android:orientation="horizontal">

<CheckBox

android:id="@+id/checkbox2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:button="@xml/custom_checkbox"/>

<TextView

android:id="@+id/textview2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textSize="14dip"

android:gravity="center"

android:padding="10dip"

android:text="(unchecked)" />

</LinearLayout>

</LinearLayout>

5. Implement our Main.java file in the /src directory. The heavy lifting is done in our XML files, so we need to simply wire the click handlers and update the text labels when a click happens.

Main.java
package com.authorwjf.checkit;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.TextView;
public class Main extends Activity implements OnClickListener {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.main);

findViewById(R.id.checkbox1).setOnClickListener(this); findViewById(R.id.checkbox2).setOnClickListener(this); }
@Override
public void onClick(View v) {

TextView tv;

if (v.getId()==R.id.checkbox1) {

tv = (TextView)findViewById(R.id.textview1);

} else {

tv = (TextView)findViewById(R.id.textview2);

}

if (((CheckBox)v).isChecked()) {

tv.setText("(checked)");

} else {

tv.setText("(unchecked)");

}

}

}
There you have it -- an entirely custom checkbox (Figure A). Remember when you are styling a checkbox that it's the button and not the background property, and everything else should be smooth sailing. Figure A

About

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

2 comments
BRomeroT
BRomeroT

It's a lot of work for something so simple! Designing that in Windows Phone use just in 6 clicks!

BRomeroT
BRomeroT

??cuant??simo trabajo para algo tan simple! En Windows Phone ese se hace en 6 clicks!!