12

I have multiple radio buttons which I want to layout using a table but also include them in a single radio group. I have the following xml layout:

<RadioGroup android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:orientation="vertical"
      android:id="@+id/Group1">

    <TableLayout android:id="@+id/RadioButtons" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content">

        <TableRow>
            <RadioButton android:id="@+id/rad1" 
                android:text="RButton1" 
                android:layout_width="105px" 
                android:layout_height="wrap_content" 
                android:textSize="13px"></RadioButton>
            <RadioButton android:id="@+id/rad2" 
                android:text="RButton2" 
                android:layout_width="105px" 
                android:textSize="13px" 
                android:layout_height="wrap_content"></RadioButton>
            <RadioButton android:id="@+id/rad3" 
                android:text="RButton3" 
                android:layout_width="105px" 
                android:textSize="13px" 
                android:layout_height="wrap_content"></RadioButton>
        </TableRow>
      </TableLayout>
</RadioGroup>  

But unfortunately the radio buttons inside the table seem to ignore the fact that they're inside of the RadioGroup tags and because of this you can select more than one radio button at the time. I noticed that by removing the table and just having the radio buttons it works just fine. How can I overcome this? Would it be as simple as declaring the radio group inside of the table instead of outside? Thanks for any help.

Fizz
  • 3,427
  • 4
  • 27
  • 43

3 Answers3

7

Your RadioButton widgets must be immediate children of the RadioGroup for the group effect to work.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • So there is no way to structure the buttons with a table and have them part of a radio group? – Fizz Mar 02 '10 at 13:24
  • Only if the `RadioButton` widgets are immediate children of the `RadioGroup`. Hence, your `RadioButton` widgets will need to be in a row or column in a single cell of your table. – CommonsWare Mar 02 '10 at 13:43
  • What if I programatically assign each radio button to be in a group? – nobalG Nov 07 '14 at 14:15
  • @nobalG: Whether the `RadioButtons` are added as children of the `RadioGroup` via a layout or via Java code should not matter. – CommonsWare Nov 07 '14 at 17:42
4

Here is my RadioGroup/RadioButton extension (SoftRadioGroup/SoftRadioButton). RadioGroup is no more needed in the layout XML. You can group the RadioButtons with a property called group.

SoftRadioButton:

import java.util.HashMap;
import java.util.Random;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.RadioButton;

public class SoftRadioButton extends RadioButton {

    private static HashMap<String, SoftRadioGroup> GROUP_MAPPINGS = new HashMap<String, SoftRadioGroup>();
    private String mGroupName;

    public SoftRadioButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        addToGroup(attrs);
    }

    public SoftRadioGroup getRadioGroup() {
        return GROUP_MAPPINGS.get(mGroupName);
    }

    private void addToGroup(AttributeSet attrs) {
        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            if (attrs.getAttributeName(i).equals("group")) {
                String groupName = attrs.getAttributeValue(i);
                SoftRadioGroup group;
                if ((group = GROUP_MAPPINGS.get(groupName)) != null) {
                    // RadioGroup already exists
                    group.addView(this);
                    setOnClickListener(group);
                    mGroupName = groupName;

                } else {
                    // this is the first RadioButton in the RadioGroup
                    group = new SoftRadioGroup();
                    group.addView(this);
                    mGroupName = groupName;
                    setOnClickListener(group);

                    GROUP_MAPPINGS.put(groupName, group);
                }
                return;
            }
        }
        // group is not specified in the layout xml. Let's generate a random
        // RadioGroup
        SoftRadioGroup group = new SoftRadioGroup();
        group.addView(this);
        Random rn = new Random();
        String groupName;
        do {
            groupName = Integer.toString(rn.nextInt());
        } while (GROUP_MAPPINGS.containsKey(groupName));
        GROUP_MAPPINGS.put(groupName, group);
        mGroupName = groupName;
        setOnClickListener(group);

    }

}

SoftRadioGroup:

import java.util.ArrayList;

import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RadioButton;

public class SoftRadioGroup implements OnClickListener {

    private ArrayList<RadioButton> buttons = new ArrayList<RadioButton>();

    public void addView(RadioButton button) {
        buttons.add(button);
    }

    @Override
    public void onClick(View v) {
        for (RadioButton button : buttons) {
            button.setChecked(false);
        }
        RadioButton button = (RadioButton) v;
        button.setChecked(true);
    }

    public RadioButton getCheckedRadioButton() {
        for (RadioButton button : buttons) {
            if (button.isSelected())
                return button;
        }
        return null;
    }

    public int getChildCount() {
        return buttons.size();
    }

    public RadioButton getChildAt(int i) {
        return buttons.get(i);
    }

    public void check(SoftRadioButton button) {
        if (buttons.contains(button)) {
            for (RadioButton b : buttons) {
                b.setChecked(false);
            }
        }
    }

}

Usage in XML layout embedded in a table (2 groups with 2 buttons per group):

<TableLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:stretchColumns="1" >

            <TableRow
                android:id="@+id/tableRow1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" >

                <Your.Package.SoftRadioButton
                    android:id="@+id/filterActivity_RadioButton_byDate"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:checked="true"
                    android:contentDescription="date"
                    android:text="@string/filterActivity_RadioButton_byDate"
                    fake:group="orderBy" />

                <Your.Package.SoftRadioButton
                    android:id="@+id/filterActivity_RadioButton_byPrice"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:contentDescription="price"
                    android:text="@string/filterActivity_RadioButton_byPrice"
                    fake:group="orderBy" />
            </TableRow>

            <TableRow
                android:id="@+id/tableRow2"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" >

                <Your.Package.SoftRadioButton
                    android:id="@+id/filterActivity_RadioButton_asc"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:contentDescription="down"
                    android:text="@string/filterActivity_RadioButton_asc"
                    fake:group="direction" />

                <Your.Package.SoftRadioButton
                    android:id="@+id/filterActivity_RadioButton_desc"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:checked="true"
                    android:contentDescription="up"
                    android:text="@string/filterActivity_RadioButton_desc"
                    fake:group="direction" />
            </TableRow>
        </TableLayout>
Remarkable
  • 549
  • 1
  • 3
  • 10
  • Warning: the code will leak views. It will add to the static map all the SoftRadioButton-views each time the views are created. Its a great idea to solve the problem with a custom view. I good solution could be to add the ViewGroup somewhere at the root of the view hierarchy and let it find all child views and pair them into groups. – arberg Jun 08 '16 at 14:29
  • Fix attribute 'group' by adding attr.xml: , and import in xml-layout the line xmlns:fake="http://schemas.android.com/apk/res-auto" – arberg Jun 08 '16 at 14:31
  • A quickfix for the memory-leak: Add to SoftRadioButton the method onDetachedFromWindow() and call GROUP_MAPPINGS.remove(mGroupName); – arberg Jun 08 '16 at 14:37
  • This was very useful, I added a new constructor with the groupname as a String to be able to create these dynamically. – Rodin10 Jul 24 '20 at 08:02
0
rg1 = (RadioGroup)findViewById(R.id.radioGroup1);
        rg2 = (RadioGroup)findViewById(R.id.radioGroup2);
        rg1.setOnCheckedChangeListener(this);
        rg2.setOnCheckedChangeListener(this);
    }
    boolean rg1b = false;
    boolean rg2b = false;

    @Override
    public void onCheckedChanged(RadioGroup rgId, int radioButtonId) {
        switch (rgId.getId()) {
        case R.id.radioGroup1:
            rg1b=true;
            if(rg2b)
                rg2.clearCheck();
            break;

        case R.id.radioGroup2:
            rg1b=true;
            if(rg1b)
                rg1.clearCheck();
            break;
        }
abdul
  • 1