Text below RadioButtons

Viewed 12805

I need your help to solve my layout problem.. I have 4 RadioButtons, they appear as usual in this scheme:

O text1   O text2   O text3   O text4

where O is the button.. I would know if it's possible to change this layout in this way:

  O       O       O       O

text1  text2  text3  text4

5 Answers

In the XML file:

<!--...-->

<RadioGroup
    android:checkedButton="@+id/radioButton1"
    android:id="@+id/radioGroupBase"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <LinearLayout
        android:background="?attr/selectableItemBackgroundBorderless"
        android:clickable="true"
        android:focusable="true"
        android:id="@+id/linearLayout1"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >
        
        <RadioButton
            android:clickable="false"
            android:focusable="false"
            android:id="@+id/radioButton1"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_width="match_parent" />
        
        <TextView
            android:clickable="false"
            android:focusable="false"
            android:id="@+id/textView1"
            android:text="@string/textView1_Text"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_width="match_parent" />
        
    </LinearLayout>
    
    <LinearLayout
        android:background="?attr/selectableItemBackgroundBorderless"
        android:clickable="true"
        android:focusable="true"
        android:id="@+id/linearLayout2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >
        
        <RadioButton
            android:clickable="false"
            android:focusable="false"
            android:id="@+id/radioButton2"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_width="match_parent" />
        
        <TextView
            android:clickable="false"
            android:focusable="false"
            android:id="@+id/textView2"
            android:text="@string/textView2_Text"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:layout_width="match_parent" />
        
    </LinearLayout>
    
    <!--more RadioButtons-->

</RadioGroup>

<!--...-->

Set up onClick() listeners for the LinearLayouts (not for RadioButtons) in the onCreate() procedure (don't forget to import android.view.View; and import android.widget.RadioGroup;):

//...

findViewById(R.id.linearLayout1).setOnClickListener(new View.OnClickListener()
{
    public void onClick(final View objView)
    {
        ((RadioGroup) findViewById(R.id.radioGroupBase)).check(findViewById(R.id.radioButton1).getId());
    }
});

findViewById(R.id.linearLayout2).setOnClickListener(new View.OnClickListener()
{
    public void onClick(final View objView)
    {
        ((RadioGroup) findViewById(R.id.radioGroupBase)).check(findViewById(R.id.radioButton2).getId());
    }
});

//more SetOnClickListener() calls for more LinearLayouts ("RadioButtons")

//...

All that's left is to set up an onCheckedChanged() listener for the RadioGroup in the same onCreate() procedure:

//...

((RadioGroup) findViewById(R.id.radioGroupBase)).setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
{
    public void onCheckedChanged(final RadioGroup objRadioGroup, final int nCheckedID)
    {
        if (!objRadioGroup.isShown())
            return;
        
        //do something depending on which RadioButton was checked
    }
});

//...

It might be a good idea to make a simple getter for the RadioGroup and maybe for the LinearLayouts as well (the latter would require import android.widget.LinearLayout;):

//...

private RadioGroup Get_radioGroupBase() { return findViewById(R.id.radioGroupBase); }
private LinearLayout Get_linearLayout1() { return findViewById(R.id.linearLayout1); }
private LinearLayout Get_linearLayout2() { return findViewById(R.id.linearLayout2); }
//more getters for more LinearLayouts ("RadioButtons")

//...

For now, radio button text positioning can easily be adjusted with MaterialRadioButton.

Radio button with text below

<com.google.android.material.radiobutton.MaterialRadioButton
    android:id="@+id/rbThemeLight"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:button="@null"
    android:drawableTop="@drawable/rb_selector"
    android:drawablePadding="4dp"
    android:gravity="center"
    android:padding="6dp"
    android:text="@string/settings_theme_light" />

A few notes here:

  1. With android:button="@null" you disable the default radio button drawable.
  2. You set a custom drawable with android:drawableTop There are other options available, sich as drawableTop, drawableEnd etc.

For the drawable you may use something like:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:enterFadeDuration="@android:integer/config_shortAnimTime" android:exitFadeDuration="@android:integer/config_shortAnimTime">

    <item android:state_checked="true">
        <shape android:shape="oval">
            <stroke android:width="5dp" android:color="@color/colorWs" />
            <size android:width="20dp" android:height="20dp" />
        </shape>
    </item>

    <item>
        <shape android:shape="oval">
            <stroke android:width="1.5dp" android:color="@color/colorClay" />
            <size android:width="20dp" android:height="20dp" />
        </shape>
    </item>

</selector>

It works either with and without a RadioGroup.

Related