Developer

Pro tip: Give Android buttons a face-lift with this customization trick

With this Android radio button makeover, the button will look a lot more attractive in your app and still function as expected.

android_610x246.png

The Android SDK comes with a lot of great UI widgets — two I use frequently are the radio group and the radio button. Unfortunately even in Android 4.4 KitKat, the default implementation is sort of ugly.

defaultradiobutton041714.png

As developers on an open platform, we have the capability to completely customize the appearance of the radio button widget. Better yet, it's pretty easy to do.

In this tutorial, I walk you through giving the standard radio button a face-lift. Feel free to follow along or download and import the project directly into Eclipse.

1. Create a new Android project in Eclipse. Target SDK 8 or better.

2. In the /res folder, create a new directory called drawable. Add the following XML resources.

radio_off.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="#ffffffff" />

    <stroke
        android:width="3dp"
        android:color="#ff848482" />

    <corners android:radius="15dp" />

</shape>

radio_on_green.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="#ff00ff00" />

    <stroke
        android:width="3dp"
        android:color="#ff00ff00" />

    <corners android:radius="15dp" />

</shape>

radio_on_red.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="#ffff0000" />

    <stroke
        android:width="3dp"
        android:color="#ffff0000" />

    <corners android:radius="15dp" />

</shape>

radio_on_yellow.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="#ffdaa520" />

    <stroke
        android:width="3dp"
        android:color="#ffdaa520" />

    <corners android:radius="15dp" />

</shape>

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

    <item android:drawable="@drawable/radio_on_green" android:state_checked="true" android:state_pressed="false"/>
    <item android:drawable="@drawable/radio_off" android:state_checked="false" android:state_pressed="false"/>

</selector>

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

    <item android:drawable="@drawable/radio_on_red" android:state_checked="true" android:state_pressed="false"/>
    <item android:drawable="@drawable/radio_off" android:state_checked="false" android:state_pressed="false"/>

</selector>

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

    <item android:drawable="@drawable/radio_on_yellow" android:state_checked="true" android:state_pressed="false"/>
    <item android:drawable="@drawable/radio_off" android:state_checked="false" android:state_pressed="false"/>

</selector>

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

    <item android:color="#ffffffff" android:state_checked="true"/>
    <item android:color="#ff848482" android:state_checked="false"/>

</selector>

3. In the /res/layout folder, create the layout for our demo.

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_gravity="center"
    android:gravity="center">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Standard Radio Buttons" />
    
    <RadioGroup
        android:id="@+id/standard_radio_group"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" 
        android:padding="20dp"
        android:orientation="horizontal"
        android:layout_below="@+id/title">
        
        <RadioButton 
            android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
   			android:text="Yes"
   			android:padding="10dp"
   			android:layout_weight=".335"
   			android:gravity="center"/>
        
        <RadioButton 
            android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:padding="10dp"
   			android:layout_marginLeft="10dp"
   			android:layout_marginRight="10dp"
   			android:text="No"
   			android:layout_weight=".335"
   			android:gravity="center"/>
        
        <RadioButton 
            android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:padding="10dp"
   			android:text="Maybe"
   			android:layout_weight=".335"
    	    android:gravity="center"/>
   
   </RadioGroup> 
   
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#ff000000"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:layout_marginRight="12dp"
        android:layout_marginLeft="12dp" />
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fancy Radio Buttons" />
    
    <RadioGroup
        android:id="@+id/fancy_radio_group"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" 
        android:padding="20dp"
        android:orientation="horizontal"
        android:layout_below="@+id/title">
        
        <RadioButton 
            android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
   			android:button="@null"
   			android:background="@drawable/radio_states_green"
   			android:text="Yes"
   			android:padding="10dp"
   			android:textColor="@drawable/radio_text"
   			android:layout_weight=".335"
   			android:gravity="center"/>
        
        <RadioButton 
            android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:background="@drawable/radio_states_red"
   			android:button="@null"
   			android:padding="10dp"
   			android:layout_marginLeft="10dp"
   			android:layout_marginRight="10dp"
   			android:textColor="@drawable/radio_text"
   			android:text="No"
   			android:layout_weight=".335"
   			android:gravity="center"/>
        
        <RadioButton 
            android:layout_width="wrap_content"
    		android:layout_height="wrap_content"
    		android:background="@drawable/radio_states_yellow"
   			android:button="@null"
   			android:padding="10dp"
   			android:textColor="@drawable/radio_text"
   			android:text="Maybe"
   			android:layout_weight=".335"
    	    android:gravity="center"/>
   
   </RadioGroup> 

</LinearLayout>

4. With the bulk of the work accomplished in the XML resources, what remains is simply to wire up the radio group on change listener and echo the results to the screen via a toast message. This can be accomplished with just a few lines of code in the /src/MainActivity.java file. Notice there is no code related to the appearance or drawing of the customized widget.

MainActivity.java
package com.authorwjf.fancyradiobuttons;

import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity implements OnCheckedChangeListener {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		((RadioGroup)findViewById(R.id.fancy_radio_group)).setOnCheckedChangeListener(this);
		((RadioGroup)findViewById(R.id.standard_radio_group)).setOnCheckedChangeListener(this);
	}

	@Override
	public void onCheckedChanged(RadioGroup group, int checkedId) {
		String groupName ="";
		if (group.getId() == R.id.standard_radio_group) {
			groupName+="Standard radio group: ";
		} else {
			groupName+="Fancy radio group: ";
		}
		RadioButton rb = (RadioButton) findViewById(checkedId);
		Toast.makeText(this, groupName+rb.getText(), Toast.LENGTH_LONG).show();
	}

}

Go ahead and load the app to a device or emulator and give the radio button a few taps. It is hardly recognizable next to the default implementation and yet provides identical functionality.

androidradiobuttonfiga041714.png

androidradiobuttonfigb041714.png

androidradiobuttonfigc041714.png

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...

Editor's Picks

Free Newsletters, In your Inbox