Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom layout for RadioButton

Is there any way I can change the layout for a RadioButton and still have the RadioGroup recognise it?

what I need is that the layout will include a couple of EditText fields so that when the user selected that button those fields become active. I know I can built a custom part based on LinearLayout and set my own layout using: (LinearLayout) LayoutInflater.from(context).inflate(R.layout.my_layout, this, true) but can't figure out how to do the same thing with a radio button.

I have tried the option of having the extra fields outside the RadioGroup and lining them up with the button but it simply doesn't work. It seems to be too device-dependant.

This is what the original layout looked like:

    <RadioGroup
    android:id="@+id/time_selector_radio_group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_hours_prompt"
    android:layout_below="@id/time_selector_hours_prompt"
    android:layout_alignParentRight="true"
    android:gravity="right"
    android:orientation="vertical"
    android:checkedButton="@+id/time_selector_first_radio"
    >

    <RadioButton
        android:id="@+id/time_selector_first_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@drawable/radio_button_selector"
        />
    <RadioButton
        android:id="@+id/time_selector_second_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@drawable/radio_button_selector"
        />
    <RadioButton
        android:id="@+id/time_selector_third_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@drawable/radio_button_selector"
        />
    <RadioButton
        android:id="@+id/time_selector_hours_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@drawable/radio_button_selector"
        />

</RadioGroup>
<TextView
    android:id="@+id/time_selector_all_day_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_radio_group"
    android:layout_below="@id/time_selector_hours_prompt"
    android:layout_marginTop="11dip"
    android:text="@string/time_all_day"
    />
<TextView
    android:id="@+id/time_selector_before_noon_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_radio_group"
    android:layout_below="@id/time_selector_all_day_prompt"
    android:layout_marginTop="19dip"
    android:text="@string/time_before_noon"
    />
<TextView
    android:id="@+id/time_selector_after_noon_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_radio_group"
    android:layout_below="@id/time_selector_before_noon_prompt"
    android:layout_marginTop="19dip"
    android:text="@string/time_after_noon"
    />
<TextView
    android:id="@+id/time_selector_starting_time_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignRight="@id/time_selector_starting_date_prompt"
    android:layout_below="@id/time_selector_after_noon_prompt"
    android:layout_marginTop="20dip"
    android:layout_marginLeft="2dip"
    android:text="@string/advanced_time_selector_dialog_starting_time_prompt"
    />
<EditText
    android:id="@+id/time_selector_starting_time"
    android:layout_width="@dimen/advanced_time_selector_edit_texts_width"
    android:layout_height="wrap_content"
    android:layout_alignRight="@id/time_selector_starting_date"
    android:layout_alignBaseline="@id/time_selector_starting_time_prompt"
    android:textSize="14sp"
    android:paddingRight="10dip"
    android:paddingLeft="10dip"
    android:gravity="center"
    android:singleLine="true"
    android:maxWidth="@dimen/advanced_time_selector_edit_texts_width"
    android:background="@drawable/text_field_bg"
    android:inputType="datetime"
    />
<TextView
    android:id="@+id/time_selector_ending_time_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignRight="@id/time_selector_ending_date_prompt"
    android:layout_alignBottom="@id/time_selector_starting_time_prompt"
    android:layout_alignBaseline="@id/time_selector_starting_time_prompt"
    android:layout_marginRight="2dip"
    android:layout_marginLeft="2dip"
    android:text="@string/ending_date_prompt"
    />
<EditText
    android:id="@+id/time_selector_ending_time"
    android:layout_width="@dimen/advanced_time_selector_edit_texts_width"
    android:layout_height="wrap_content"
    android:layout_alignRight="@id/time_selector_ending_date"
    android:layout_alignBaseline="@id/time_selector_ending_time_prompt"
    android:textSize="14sp"
    android:paddingRight="10dip"
    android:paddingLeft="10dip"
    android:gravity="center"
    android:singleLine="true"
    android:maxWidth="@dimen/advanced_time_selector_edit_texts_width"
    android:background="@drawable/text_field_bg"
    android:inputType="datetime"
    />

Note that the button doesn't have any text and it is added in a TextView so that we can have it on the left. What was happening was that the text was "creeping up".

So, I changed it to look like this:

<RadioGroup
    android:id="@+id/time_selector_radio_group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_hours_prompt"
    android:layout_below="@id/time_selector_hours_prompt"
    android:layout_alignParentRight="true"
    android:layout_marginRight="30dip"
    android:gravity="right"
    android:orientation="vertical"
    android:checkedButton="@+id/time_selector_first_radio"
    >

    <RadioButton
        android:id="@+id/time_selector_all_day_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@null"
        android:drawableRight="@drawable/radio_button_selector"
        android:text="@string/time_all_day"
        android:textColor="@color/content_text_color"
        />
    <RadioButton
        android:id="@+id/time_selector_before_noon_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@null"
        android:drawableRight="@drawable/radio_button_selector"
        android:text="@string/time_before_noon"
        android:textColor="@color/content_text_color"
        />

    <RadioButton
        android:id="@+id/time_selector_after_noon_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@null"
        android:drawableRight="@drawable/radio_button_selector"
        android:text="@string/time_after_noon"
        android:textColor="@color/content_text_color"
        />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">   
        <RadioButton
            android:id="@+id/time_selector_hours_radio"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="1dip"
            android:button="@null"
            android:drawableRight="@drawable/radio_button_selector"
            android:layout_alignParentRight="true"
            android:text="@string/advanced_time_selector_dialog_starting_time_prompt"
            android:textColor="@color/content_text_color"
            android:layout_marginLeft="-1dip"
            android:paddingLeft="-1dip"
            />  
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_toLeftOf="@id/time_selector_hours_radio"
            android:layout_alignParentLeft="true">            
            <EditText
                android:id="@+id/time_selector_starting_time"
                android:layout_width="@dimen/advanced_time_selector_edit_texts_width"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:paddingRight="10dip"
                android:paddingLeft="10dip"
                android:gravity="center"
                android:singleLine="true"
                android:maxWidth="@dimen/advanced_time_selector_edit_texts_width"
                android:background="@drawable/text_field_bg"
                android:layout_alignParentRight="true"
                android:layout_alignBaseline="@id/time_selector_hours_radio"
                android:inputType="datetime"
                />
            <TextView
                android:id="@+id/time_selector_ending_time_prompt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="2dip"
                android:layout_marginLeft="2dip"
                android:text="@string/ending_date_prompt"
                android:layout_alignBaseline="@id/time_selector_hours_radio"
                android:layout_toLeftOf="@id/time_selector_starting_time"
                />
            <EditText
                android:id="@+id/time_selector_ending_time"
                android:layout_width="@dimen/advanced_time_selector_edit_texts_width"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:paddingRight="10dip"
                android:paddingLeft="10dip"
                android:gravity="center"
                android:singleLine="true"
                android:maxWidth="@dimen/advanced_time_selector_edit_texts_width"
                android:layout_toLeftOf="@id/time_selector_ending_time_prompt"
                android:layout_alignBaseline="@id/time_selector_hours_radio"
                android:background="@drawable/text_field_bg"
                android:inputType="datetime"
                />
        </RelativeLayout>
    </RelativeLayout>

</RadioGroup>

It is still not perfect and, of course, it doesn't recognise it as a RadioGroup.

I wanted to go the direction of extending the RadioButton but have no idea how to change the layout there.

like image 381
theblitz Avatar asked May 13 '13 06:05

theblitz


People also ask

How do I get radio buttons side by side on android?

Use the android:orientation="horizontal" -attribute of the RadioGroup.

How can we create radio buttons?

To create each radio button option, create a RadioButton in your layout. However, because radio buttons are mutually exclusive, you must group them together inside a RadioGroup . By grouping them together, the system ensures that only one radio button can be selected at a time.

How do I create a horizontal radio button?

To make a horizontal radio button set, add the data-type="horizontal" to the fieldset . The framework will float the labels so they sit side-by-side on a line, hide the radio button icons and only round the left and right edges of the group.

How do you create a dynamic radio button?

For creating dynamic RadioButton, we need to use android. view. ViewGroup. LayoutParams which configures the width and height of views and implements setOnCheckedChangeListener() method of RadioGroup class.


2 Answers

I wrote a custom RadioGroup called RadioGroupPlus where it will traverse through it's children and find RadioButton regardless how deep the RadioButton is nested, it will then link all the RadioButton found together.

You can find the repo here: https://github.com/worker8/RadioGroupPlus

The README of the repo covers how to use it, and it actually works just like how you imagine it, for example:

<worker8.com.github.radiogroupplus.RadioGroupPlus
    android:id="@+id/radio_group_plus"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <LinearLayout...>
       <ImageView...>
       <TextView...>
       <RadioButton...>
    </LinearLayout>
    <LinearLayout...>
       <ImageView...>
       <TextView...>
       <RadioButton...>
    </LinearLayout>
    <LinearLayout...>
       <ImageView...>
       <TextView...>
       <RadioButton...>
    </LinearLayout>
</worker8.com.github.radiogroupplus.RadioGroupPlus>

Will give you something like this:

In your case, since you already have the xml layout file, try to download RadioGroupPlus by following the guide here:

Add this to top level build.gradle:

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}

Add this under dependencies:

compile 'com.github.worker8:RadioGroupPlus:v1.0.1'

Then in your xml, change RadioGroup to worker8.com.github.radiogroupplus.RadioGroupPlus. Now all your RadioButtons under RadioGroupPlus should all be linked together.

Hope it helps!

like image 117
I'm a frog dragon Avatar answered Oct 20 '22 09:10

I'm a frog dragon


You'll have to create a class that extends RadioGroup, and override addView and PassThroughHierarchyChangeListener, to be able to use custom layouts for your radio button. By default, RadioGroup assumes that its children are radio buttons, see code below from the RadioGroup class:

@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
    if (child instanceof RadioButton) {
        final RadioButton button = (RadioButton) child;
        if (button.isChecked()) {
            mProtectFromCheckedChange = true;
            if (mCheckedId != -1) {
                setCheckedStateForView(mCheckedId, false);
            }
            mProtectFromCheckedChange = false;
            setCheckedId(button.getId());
        }
    }

    super.addView(child, index, params);
}

private class PassThroughHierarchyChangeListener implements
        ViewGroup.OnHierarchyChangeListener {
    private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;

    /**
     * {@inheritDoc}
     */
    public void onChildViewAdded(View parent, View child) {
        if (parent == RadioGroup.this && child instanceof RadioButton) {
            int id = child.getId();
            // generates an id if it's missing
            if (id == View.NO_ID) {
                id = View.generateViewId();
                child.setId(id);
            }
            ((RadioButton) child).setOnCheckedChangeWidgetListener(
                    mChildOnCheckedChangeListener);
        }

        if (mOnHierarchyChangeListener != null) {
            mOnHierarchyChangeListener.onChildViewAdded(parent, child);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void onChildViewRemoved(View parent, View child) {
        if (parent == RadioGroup.this && child instanceof RadioButton) {
            ((RadioButton) child).setOnCheckedChangeWidgetListener(null);
        }

        if (mOnHierarchyChangeListener != null) {
            mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
        }
    }
}
like image 39
Noureddine AMRI Avatar answered Oct 20 '22 09:10

Noureddine AMRI