I'm trying to create a RadioGroup
within an Android layout where the child RadioButton
s are stretched to evenly fill the entire width of the RadioGroup
. However, I've encountered some unexpected behaviour when trying to do this with RadioButton
s which have been added programmatically from code. First some background...
I started with a simple layout based on a RelativeLayout
which contains a large TextView
and a RadioGroup
at the bottom.
The main.xml layout file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView android:text="Some text"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_alignParentTop="true"
android:layout_above="@+id/radio_group"
android:gravity="center"
android:background="@android:color/holo_green_dark"
/>
<RadioGroup android:id="@+id/radio_group"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:background="@android:color/holo_blue_dark">
<RadioButton android:text="Option 1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_weight="1"
android:background="@android:color/darker_gray"
android:button="@android:color/transparent"
android:padding="10dp"
android:gravity="center"
android:layout_margin="2dp"/>
<RadioButton android:text="Option 2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_weight="1"
android:background="@android:color/darker_gray"
android:button="@android:color/transparent"
android:padding="10dp"
android:gravity="center"
android:layout_margin="2dp"/>
</RadioGroup>
</RelativeLayout>
which produces the following layout at runtime:
You can see that the use of android:layout_width="wrap_content"
and android:layout_weight="1"
in both RadioButton
s stretches them to evenly fill half of the enclosing RadioGroup
each. So far so good.
However, the requirement I have is to dynamically create RadioButton
s within this layout at runtime based on business logic rather than always using the the two statically included in the layout - sometimes I might need two buttons, sometimes four etc.
To implement this I removed the RadioButton
s from my main.xml layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView android:text="Some text"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_alignParentTop="true"
android:layout_above="@+id/radio_group"
android:gravity="center"
android:background="@android:color/holo_green_dark"
/>
<RadioGroup android:id="@+id/radio_group"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:background="@android:color/holo_blue_dark"/>
</RelativeLayout>
...and created a separate _radio_button.xml_ layout for my RadioButton
:
<?xml version="1.0" encoding="utf-8"?>
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:layout_weight="1"
android:background="@android:color/darker_gray"
android:button="@android:color/transparent"
android:gravity="center"
android:padding="10dp" />
In my activity I now add the RadioButton
s programmatically:
public class TestRadioActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create an inflater to inflate our buttons
LayoutInflater inflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Create the layout params for our buttons
LinearLayout.LayoutParams layoutParams = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f);
RadioGroup group = (RadioGroup) findViewById(R.id.radio_group);
// Add button one
RadioButton button = (RadioButton) inflater.inflate(R.layout.radio_button, null);
button.setText("Option 1");
group.addView(button, layoutParams);
// Add button two
button = (RadioButton) inflater.inflate(R.layout.radio_button, null);
button.setText("Option 2");
group.addView(button, layoutParams);
}
}
Note how both the _radio_button.xml_ file and the activity specify a layout width of WRAP_CONTENT and a layout weight of 1 to evenly distribute the buttons as in the original main.xml.
However, the layout seems to get rendered ignoring the layout weight with the buttons butted up on the left of the radio group:
As has been suggested elsewhere, I also tried setting the width of the RadioButton
s to 0 in the LayoutParams
(apparently this can cause the layout weight to be interpreted slightly differently), but this causes the RadioButton
s not even to be rendered:
Can any advise how to get RadioButton
s to evenly fill the entire width of the containing RadioGroup
when added programmatically? Is there anything obvious I'm missing?
When you set a layout weight, you should use fill_parent as layout width. Then you shouldn't use LinearLayout.LayoutParams but RadioGroup.LayoutParams, as you're adding radio buttons to a RadioGroup, not to a simple LinearLayout.
Finally, as you use the inflater to "build" the radio button, the XML file of the radio button already has the layout params picked from the XML file, so I think you should just call the addView method that takes only the view to add as parameter (that is addView(View v)
) and change the layout_width to fill_parent.
Note that, if you'll need to reference the variable "button" in the code, i.e. add a click listener, you'll add the listener only to the last created button. You'll have to create a RadioButton object for each RadioButton you will add to the RadioGroup (button, button1, button2, etc).
FYI, to do it without any xml at all
RadioGroup rgrp = new RadioGroup(context);
rgrp.setLayoutParams(new RadioGroup.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
rgrp.setOrientation(LinearLayout.HORIZONTAL);
mAccent = new RadioButton(context);
mAccent.setText("Accent");
mAccent.setLayoutParams(new RadioGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f));
rgrp.addView(mAccent);
mGhost = new RadioButton(context);
mGhost.setText( "Ghost");
mGhost.setLayoutParams(new RadioGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f));
rgrp.addView(mGhost);
mFlam = new RadioButton(context);
mFlam.setText( "Flam");
mFlam.setLayoutParams(new RadioGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f));
rgrp.addView(mFlam);
layout.addView(rgrp);
I ran into this issue too, I used the RadioGroup.LayoutParams
with weight defined. However I also found once I'd created programatically the buttons weren't responding to touch so set clickable
and enabled
to true
and that fixed things.
private RadioButton createMyTypeRadioButton(MyType type){
//create using this constructor to use some of the style definitions
RadioButton radio = new RadioButton(this, null, R.style.MyRadioStyle);
RadioGroup.LayoutParams layoutParams = new RadioGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f);
radio.setLayoutParams(layoutParams);
radio.setGravity(Gravity.CENTER);
//tag used by the setOnCheckedChangeListener to link the radio button with mytype object
radio.setTag(type.getId());
//enforce enabled and clickable status otherwise they ignore clicks
radio.setClickable(true);
radio.setEnabled(true);
radio.setText(type.getTitle());
return radio;
}
private void updateMyTypesUi() {
//populate RadioGroup with permitted my types
for (int i = 0; i < myTypes.size(); i++) {
MyType type = myTypes.get(i);
RadioButton radioButton = createSwapTypeRadioButton(type);
myRadioGrp.addView(radioButton);
}
myRadioGrp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton checkedType = (RadioButton) group.findViewById(checkedId);
String idOfMyTypeChecked = (String) checkedType.getTag();
//do something with idOfMyTypeChecked
}
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With