Decorating RadioGroup/RadioButton in Android Android 17.06.2017

RadioGroup is a widget in Android which groups RadioButtons. More specifically, the use of RadioGroup provides the capability of selecting only one RadioButton from the set. When the user chooses one RadioButton, the previous one that was selected, becomes automatically unchecked.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RadioGroup
        android:id="@+id/rgStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:checkedButton="@+id/rbVisible" >

        <RadioButton
            android:id="@+id/rbVisible"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Visible" />

        <RadioButton
            android:id="@+id/rbHidden"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hidden" />

        <RadioButton
            android:id="@+id/rbDraft"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Draft" />
    </RadioGroup>
</RelativeLayout>

The basic attribute of RadioGroup is android:checkedButton, that specifies which radio button should be checked by default. The other components are inherited from the View class. As you can notice from the code above, the set of the radio buttons are embodied by a RadioGroup, so every configuration of its component affects the radio buttons too.

public class MainActivity extends Activity {
    private RadioGroup rgStatus;
    private RadioButton rbVisible, rbHidden, rbDraft;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rgStatus = (RadioGroup) findViewById(R.id.rgStatus);

        rgStatus.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // find which radio button is selected
                if(checkedId == R.id.rbVisible) {
                    Toast.makeText(getApplicationContext(), "Visible",
                            Toast.LENGTH_SHORT).show();
                } else if(checkedId == R.id.rbHidden) {
                    Toast.makeText(getApplicationContext(), "Hidden",
                            Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(getApplicationContext(), "Draft",
                            Toast.LENGTH_SHORT).show();
                }
            }
        });

        //int selectedId = rgStatus.getCheckedRadioButtonId();
    }

    public void onButton(View v) {
        int id = rgStatus.getCheckedRadioButtonId();
        switch(id) {
            case R.id.rbVisible:
                Log.d(TAG, "Visible");
                break;
            case R.id.rbHidden:
                Log.d(TAG, "Hidden");
                break;
            case R.id.rbDraft:
                Log.d(TAG, "Draft");
                break;                        
        }
    }
}

Now let’s have a look at the code above. When a checked radio button is changed in its group, OnCheckedChangeListener is invoked in order to handle this situation. The onCheckedChanged() method of this interface, includes the unique id of the radio button that was selected and caused the invoke of the callback.

android_radiogroup.png

If you want align text of RadioButton to the left and button to the right side of parent view add following line android:layoutDirection="rtl". Following is full code for RadioButton:

<RadioButton
    android:id="@+id/rbOption1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Option 1"
    android:layoutDirection="rtl"/>

You can check the current state of a radio button programmatically by using isChecked() method.

Boolean rbVisibleState = rbVisible.isChecked();

Set the current state of a radio button

rbVisible.setChecked(true);

Get index of RadioButton in RadioGroup.

RadioButton rb = (RadioButton) rgStatus.findViewById(R.id.rbVisible);
int index = rgStatus.indexOfChild(rb);

Check RadioButton in RadioGroup by index

((RadioButton)rgStatus.getChildAt(pos)).setChecked(true);

There are drawableBottom, drawableTop, drawableLeft and drawableRight attributes which draw the drawable to the below of the text of RadioButton. For example, set drawable icon at the right of RadioButton

android:drawableRight="@drawable/ic_launcher"

Let's decorate RadioButton via android:background attribute.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RadioGroup
        android:layout_marginTop="10dp"
        android:id="@+id/rgStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal"
        android:background="@drawable/custom_rg"
        android:checkedButton="@+id/rbVisible" >

        <RadioButton
            android:id="@+id/rbVisible"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:checked="true"
            android:background="@drawable/custom_rb"
            android:button="@null"
            android:textColor="@drawable/custom_rb_text"
            android:text="Visible" />

        <RadioButton
            android:id="@+id/rbHidden"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="@drawable/custom_rb"
            android:button="@null"
            android:textColor="@drawable/custom_rb_text"
            android:text="Hidden" />

        <RadioButton
            android:id="@+id/rbDraft"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="@drawable/custom_rb"
            android:button="@null"
            android:textColor="@drawable/custom_rb_text"
            android:text="Draft" />
    </RadioGroup>
</RelativeLayout>

Create res/drawable/custom_rb_text.xml with following content.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:color="#FFFFFF"/>
    <item android:state_checked="false" android:color="@android:color/black"/>
</selector>

Create res/drawable/custom_rb.xml with following content.

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true">
        <shape android:shape="rectangle">
            <solid android:color="#CDDC38"/>
            <padding android:bottom="15dp" android:left="35dp" android:right="35dp" android:top="15dp"/>
            <corners android:radius="5dp"/>
        </shape>
    </item>

    <item android:state_checked="false">
        <shape>
            <solid android:color="#ebffffff"/>
            <padding android:bottom="15dp" android:left="35dp" android:right="35dp" android:top="15dp"/>
            <corners android:radius="5dp"/>
        </shape>
    </item>
</selector>

Create res/drawable/custom_rg.xml with following content.

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#ebffffff"/>
    <stroke android:width="1dp" android:color="#CDDC38"/>
    <corners android:radius="5dp" />
    <padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp"/>
</shape>

Result

android_radiogroup_custom_bg.png

Let's decorate RadioButton via android:button attribute.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RadioGroup
        android:layout_marginTop="10dp"
        android:id="@+id/rgStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:orientation="vertical"
        android:checkedButton="@+id/rbVisible" >

        <RadioButton
            android:id="@+id/rbVisible"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:button="@drawable/circle"
            android:textColor="#000000"
            android:text="Visible" />

        <RadioButton
            android:id="@+id/rbHidden"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:button="@drawable/circle"
            android:textColor="#000000"
            android:text="Hidden" />

        <RadioButton
            android:id="@+id/rbDraft"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:button="@drawable/circle"
            android:textColor="#000000"
            android:text="Draft" />
    </RadioGroup>
</RelativeLayout>

Create res/drawable/circle.xml with following content.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true">
        <shape android:shape="oval">
            <solid android:color="@color/colorAccent"/>
            <stroke android:width="3dp" android:color="@color/colorPrimary"/>
            <size android:height="27dp" android:width="27dp" />
        </shape>
    </item>

    <item android:state_checked="false">
        <shape android:shape="oval">
            <solid android:color="@color/colorAccent"/>
            <stroke android:width="3dp" android:color="@android:color/white"/>
            <size android:height="27dp" android:width="27dp" />
        </shape>
    </item>
</selector>

Result

android_radiogroup_custom_button.png

If you want to change the color of circle of radio button you can use following snippet

<android.support.v7.widget.AppCompatRadioButton
    android:id="@+id/rbCircle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:buttonTint="@color/primary" />

Also, you can declare custom style in your styles.xml file.

<style name="MyRadioButton" parent="Theme.AppCompat.Light">  
  <item name="colorControlNormal">@color/indigo</item>
  <item name="colorControlActivated">@color/pink</item>
</style>  

Apply this style to your RadioButton via android:theme attribute.

<RadioButton  
    android:text="Circle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="true"
    android:theme="@style/MyRadioButton"/>

Implementing RadioButtons programmatically

Let’s say you want to populate a RadioGroup with selections from a database, or some other reason that necessitates doing so programmatically instead of using a layout file. I recommend you include an empty RadioGroup control in your layout file, for design purposes. Make sure it has a unique identifier associated with it so it can be accessed programmatically.

In your Activity class (for example, in your onCreate() method), create and add RadioButton controls, like this:

RadioGroup rgItems = (RadioGroup) findViewById(R.id.rgItems);

OnClickListener listener = new OnClickListener() {
    public void onClick(View v) {
        onRadioButtonClick(v);
    }
};

RadioButton button1 = new RadioButton(this);
button1.setText("Item 1");
button1.setTextColor(Color.RED);
button1.setOnClickListener(listener); 
rgItems.addView(button1);

RadioButton button2 = new RadioButton(this);
button2.setText("Item 2");
button2.setTextColor(Color.GREEN);
button2.setOnClickListener(listener);
rgItems.addView(button2);

RadioButton button3 = new RadioButton(this);
button3.setText("Item 3");
button3.setTextColor(Color.BLUE);
button3.setOnClickListener(listener);  
rgItems.addView(button3);

rgItems.check(button1.getId());

First, we find the empty RadioGroup which was defined in our layout file (see the source code for details if you need more information). Then we create three RadioButton controls, set their text, text color, and onClickListener attributes programmatically. Finally, we add each to the RadioGroup parent control and set the red RadioButton to be checked by default using the check() method of the RadioGroup class.