I have a RadioGroup
and I want to align buttons next to each other in two columns and five rows and I am unable to achieve it. Things I have tried:
I created my own RadioGridLayout which include RadioGroup code and extends GridLayout. You can copy this code. For me working well. After you can use this layout in your xml. And customize like grid layout.
For R.styleable.RadioGridLayout_checked I used code like this:
<resources>
<declare-styleable name="RadioGridLayout">
<attr name="checked" format="integer" />
</declare-styleable>
</resources>
public class RadioGridLayout extends GridLayout {
private int mCheckedId = -1;
private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
private boolean mProtectFromCheckedChange = false;
private OnCheckedChangeListener mOnCheckedChangeListener;
private PassThroughHierarchyChangeListener mPassThroughListener;
private void setCheckedId(@IdRes int id) {
mCheckedId = id;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
}
AutofillManager afm = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
afm = getContext().getSystemService(AutofillManager.class);
}
if (afm != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
afm.notifyValueChanged(this);
}
}
}
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
mOnCheckedChangeListener = listener;
}
public interface OnCheckedChangeListener {
void onCheckedChanged(RadioGridLayout group, @IdRes int checkedId);
}
private int mInitialCheckedId = View.NO_ID;
public RadioGridLayout(Context context) {
super(context);
setOrientation(VERTICAL);
init();
}
public RadioGridLayout(Context context, AttributeSet attrs) {
super(context, attrs);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
}
TypedArray attributes = context.obtainStyledAttributes(
attrs,
R.styleable.RadioGridLayout,
R.attr.radioButtonStyle, 0);
int value = attributes.getResourceId(R.styleable.RadioGridLayout_checked, View.NO_ID);
if (value != View.NO_ID) {
mCheckedId = value;
mInitialCheckedId = value;
}
attributes.recycle();
init();
}
private void init() {
mChildOnCheckedChangeListener = new CheckedStateTracker();
mPassThroughListener = new PassThroughHierarchyChangeListener();
super.setOnHierarchyChangeListener(mPassThroughListener);
}
@Override
public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
mPassThroughListener.mOnHierarchyChangeListener = listener;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (mCheckedId != -1) {
mProtectFromCheckedChange = true;
setCheckedStateForView(mCheckedId, true);
mProtectFromCheckedChange = false;
setCheckedId(mCheckedId);
}
}
@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);
}
public void check(@IdRes int id) {
if (id != -1 && (id == mCheckedId)) {
return;
}
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
if (id != -1) {
setCheckedStateForView(id, true);
}
setCheckedId(id);
}
private void setCheckedStateForView(int viewId, boolean checked) {
View checkedView = findViewById(viewId);
if (checkedView != null && checkedView instanceof RadioButton) {
((RadioButton) checkedView).setChecked(checked);
}
}
@IdRes
public int getCheckedRadioButtonId() {
return mCheckedId;
}
public void clearCheck() {
check(-1);
}
@Override
public GridLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new GridLayout.LayoutParams(getContext(), attrs);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof RadioGroup.LayoutParams;
}
@Override
protected GridLayout.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams();
}
@Override
public CharSequence getAccessibilityClassName() {
return RadioGroup.class.getName();
}
public static class LayoutParams extends GridLayout.LayoutParams {
public LayoutParams(Spec rowSpec, Spec columnSpec) {
super(rowSpec, columnSpec);
}
public LayoutParams() {
super();
}
public LayoutParams(ViewGroup.LayoutParams params) {
super(params);
}
public LayoutParams(MarginLayoutParams params) {
super(params);
}
public LayoutParams(GridLayout.LayoutParams source) {
super(source);
}
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void setBaseAttributes(TypedArray a,
int widthAttr, int heightAttr) {
if (a.hasValue(widthAttr)) {
width = a.getLayoutDimension(widthAttr, "layout_width");
} else {
width = WRAP_CONTENT;
}
if (a.hasValue(heightAttr)) {
height = a.getLayoutDimension(heightAttr, "layout_height");
} else {
height = WRAP_CONTENT;
}
}
}
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mProtectFromCheckedChange) {
return;
}
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
int id = buttonView.getId();
setCheckedId(id);
}
}
private class PassThroughHierarchyChangeListener implements
ViewGroup.OnHierarchyChangeListener {
private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;
@Override
public void onChildViewAdded(View parent, View child) {
if (parent == RadioGridLayout.this && child instanceof RadioButton) {
int id = child.getId();
if (id == View.NO_ID) {
id = View.generateViewId();
child.setId(id);
}
((RadioButton) child).setOnCheckedChangeListener(
mChildOnCheckedChangeListener);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(parent, child);
}
}
@Override
public void onChildViewRemoved(View parent, View child) {
if (parent == RadioGridLayout.this && child instanceof RadioButton) {
((RadioButton) child).setOnCheckedChangeListener(null);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
}
}
}
@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
super.onProvideAutofillStructure(structure, flags);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
}
}
@Override
public void autofill(AutofillValue value) {
if (!isEnabled()) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!value.isList()) {
Timber.w(value + " could not be autofilled into " + this);
return;
}
}
int index = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
index = value.getListValue();
}
final View child = getChildAt(index);
if (child == null) {
Timber.w("RadioGroup.autoFill(): no child with index %s", index);
return;
}
check(child.getId());
}
@Override
public int getAutofillType() {
return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
}
@Override
public AutofillValue getAutofillValue() {
if (!isEnabled()) return null;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getId() == mCheckedId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return AutofillValue.forList(i);
}
}
}
return null;
}
}
This is what i did on my XML layout and it works fine.
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioOwner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:buttonTint="@color/login_button_color"
android:fontFamily="@font/rnhousesans_regular"
android:text="Owner"
android:textColor="@color/colorPrimary" />
<RadioButton
android:id="@+id/radioLivingParents"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:buttonTint="@color/login_button_color"
android:fontFamily="@font/rnhousesans_regular"
android:text="Living with parents"
android:textColor="@color/colorPrimary" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioTenant"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:buttonTint="@color/login_button_color"
android:fontFamily="@font/rnhousesans_regular"
android:text="Tenant"
android:textColor="@color/colorPrimary" />
<RadioButton
android:id="@+id/radioOther"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:buttonTint="@color/login_button_color"
android:fontFamily="@font/rnhousesans_regular"
android:text="Other"
android:textColor="@color/colorPrimary" />
</LinearLayout>
</RadioGroup>
Make 2 RadioGroup in the xml file using LinearLayout each having 5 RadioButton and using layout_weight property place them side by side on the screen. Then create listener for these radio groups as shown below:
rg1 = (RadioGroup) findViewById(R.id.radiogroup1);
rg2 = (RadioGroup) findViewById(R.id.radiogroup2);
rg1.clearCheck();//this is so we can start fresh, with no selection on both RadioGroups
rg2.clearCheck();
rg1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
if (checkedId != -1) {
fun2();
}
}
});
rg2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
if (checkedId != -1) {
fun1();
}
}
});
And fun1() & fun2() will be defined as shown below:
public void fun1() {
rg1.setOnCheckedChangeListener(null);
rg1.clearCheck();
rg1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
fun2();
Log.v("Inside fun1","fun2");
}
});
}
public void fun2() {
rg2.setOnCheckedChangeListener(null);
rg2.clearCheck();
rg2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
fun1();
Log.v("Inside fun2","fun1");
}
});
}
You can use a nested GridLayout inside your RadioGroup, although you will loose the main property of the RadioGroup to manage RadioButtons: e.g. single item selection. RadioButtons should be direct children.
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<GridLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:columnCount="2"
>
<androidx.appcompat.widget.AppCompatRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text 1"
/>
<androidx.appcompat.widget.AppCompatRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text 2"
/>
<androidx.appcompat.widget.AppCompatRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text 3"
/>
<androidx.appcompat.widget.AppCompatRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text 4"
/>
<androidx.appcompat.widget.AppCompatRadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text 5"
/>
</GridLayout>
</RadioGroup>
I had to do the same thing and wound up combining a TableLayout and a RadioButtonGroup. I added the radio buttons dynamically to TableRows. Here is the class:
public class RadioGroupColumns extends TableLayout implements OnClickListener {
private static final String TAG = "RadioGroupColumns";
private RadioButton activeRadioButton;
private int mCheckedId = -1;
// tracks children radio buttons checked state
private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
// when true, mOnCheckedChangeListener discards events
private boolean mProtectFromCheckedChange = false;
private OnCheckedChangeListener mOnCheckedChangeListener;
private PassThroughHierarchyChangeListener mPassThroughListener;
public RadioGroupColumns(Context context) {
super(context);
setOrientation(VERTICAL);
init();
}
public RadioGroupColumns(Context context, AttributeSet attrs) {
super(context, attrs);
Resources res = Resources.getSystem();
int value = 0;
// retrieve selected radio button as requested by the user in the
// XML layout file
TypedArray attributes = null;
try {
attributes = context.obtainStyledAttributes(attrs, getAttributes(context), R.attr.radioButtonStyle, 0);
value = attributes.getResourceId(getAttribute(context), View.NO_ID);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
Log.d("Exception RadioGroupColumns Construct",e.toString());
e.printStackTrace();
}
catch (ClassNotFoundException e) {
Log.d("Exception RadioGroupColumns Construct",e.toString());
e.printStackTrace();
}
if (value != View.NO_ID) {
mCheckedId = value;
}
//hardcode it to vertical
//final int index = attributes.getInt(com.android.internal.R.styleable.RadioGroup_orientation, VERTICAL);
//setOrientation(index);
attributes.recycle();
setOrientation(VERTICAL);
init();
}
@Override
public void onClick(View v) {
if (v instanceof TableRow) {
TableRow row = (TableRow)v;
for (int j=0;j<row.getChildCount();j++) {
if (RadioButton.class.isAssignableFrom(row.getChildAt(j).getClass())) {
((RadioButton) row.getChildAt(j)).setChecked(true);
activeRadioButton = (RadioButton) row.getChildAt(j);
}
}
}
else {
final RadioButton rb = (RadioButton) v;
if (activeRadioButton != null) {
activeRadioButton.setChecked(false);
}
rb.setChecked(true);
activeRadioButton = rb;
}
}
private void init() {
mChildOnCheckedChangeListener = new CheckedStateTracker();
mPassThroughListener = new PassThroughHierarchyChangeListener();
super.setOnHierarchyChangeListener(mPassThroughListener);
}
private int getAttribute(Context con) throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException {
//use reflect to get styleable class.
Field[] alFields = null;
ArrayList<Integer> alInts = new ArrayList<Integer>();
int R_ID = 0;
for (Class c : android.R.class.getClasses()) {
if (c.getName().indexOf("styleable") >= 0) {
alFields = Class.forName( con.getPackageName() + ".R$styleable" ).getFields();
}
}
for (Field f : alFields) {
Log.d("field name",f.getName());
if (f.getName().equals("RadioGroup_checkedButton")) {
int[] ret = (int[])f.get(null);
R_ID = ret[0];
}
}
return R_ID;
}
//gets all RadioGroup R,android.internal.styleable.RadioGroup values
private int[] getAttributes(Context con) throws IllegalAccessException, ClassNotFoundException {
//use reflect to get styleable class.
Field[] alFields = null;
ArrayList<Integer> alInts = new ArrayList<Integer>();
int[] ints = null;
int count = 0;
try {
for (Class c : android.R.class.getClasses()) {
if (c.getName().indexOf("styleable") >= 0) {
Log.d("get Class Name Outer", c.getName());
//use reflection to access the resource class
alFields = Class.forName( con.getPackageName() + ".R$styleable" ).getFields();
}
}
if (alFields != null)
{
Log.d("field numbers size", String.valueOf(alFields.length));
for (Field field : alFields) {
Class<?> targetType = field.getType();
Log.d("field type", field.getType().toString());
if (targetType.equals(Integer.TYPE) && targetType.isPrimitive()) {
//alInts.add((Integer)field);
Object objectValue = (Integer)field.getInt(null);
//Object objectValue = (Integer)targetType.newInstance();
alInts.add((Integer)objectValue);
count++;
}
ints = new int[count];
for (int i=0;i<alInts.size();i++) {
ints[i] = alInts.get(i);
}
}
}
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
return ints;
}
public void check(int id) {
// don't even bother
if (id != -1 && (id == mCheckedId)) {
return;
}
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
if (id != -1) {
setCheckedStateForView(id, true);
}
activeRadioButton = (RadioButton) findViewById(id);
activeRadioButton.setChecked(true);
setCheckedId(id);
}
public void setOnCheckedChangeListener(RadioGroupColumns.OnCheckedChangeListener onCheckedChangeListener) {
mOnCheckedChangeListener = (OnCheckedChangeListener) onCheckedChangeListener;
}
private void setCheckedId(int id) {
mCheckedId = id;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
}
}
private void setCheckedStateForView(int viewId, boolean checked) {
View checkedView = findViewById(viewId);
if (!RadioButton.class.isAssignableFrom(checkedView.getClass()) && checkedView != null) {
TableRow row = (TableRow) checkedView;
for (int j=0;j<row.getChildCount();j++) {
RadioButton button = (RadioButton) row.getChildAt(j);
if (button.isChecked() && button != null) {
button.setChecked(checked);
}
}
}
if (checkedView != null && checkedView instanceof RadioButton) {
((RadioButton) checkedView).setChecked(checked);
}
}
/*
* (non-Javadoc)
*
* @see android.widget.TableLayout#addView(android.view.View, int,
* android.view.ViewGroup.LayoutParams)
*/
@Override
public void addView(View child, int index,
android.view.ViewGroup.LayoutParams params) {
super.addView(child, index, params);
setChildrenOnClickListener((TableRow) child);
}
/*
* (non-Javadoc)
*
* @see android.widget.TableLayout#addView(android.view.View,
* android.view.ViewGroup.LayoutParams)
*/
@Override
public void addView(View child, android.view.ViewGroup.LayoutParams params) {
super.addView(child, params);
setChildrenOnClickListener((TableRow) child);
}
private void setChildrenOnClickListener(TableRow tr) {
final int c = tr.getChildCount();
for (int i = 0; i < c; i++) {
final View v = tr.getChildAt(i);
if (v instanceof RadioButton) {
v.setOnClickListener(this);
}
}
}
public int getCheckedRadioButtonId() {
if (activeRadioButton != null) {
return activeRadioButton.getId();
}
return -1;
}
public interface OnCheckedChangeListener {
public void onCheckedChanged(RadioGroupColumns group, int checkedId);
}
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// prevents from infinite recursion
if (mProtectFromCheckedChange) {
return;
}
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
int id = buttonView.getId();
setCheckedId(id);
}
}
private class PassThroughHierarchyChangeListener implements android.view.ViewGroup.OnHierarchyChangeListener {
private android.view.ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;
/**
* {@inheritDoc}
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public void onChildViewAdded(View parent, View child) {
if (parent == RadioGroupColumns.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).setOnCheckedChangeListener((com.assistek.ediary.RadioButton.OnCheckedChangeListener) mChildOnCheckedChangeListener);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(parent, child);
}
}
/**
* {@inheritDoc}
*/
public void onChildViewRemoved(View parent, View child) {
if (parent == RadioGroupColumns.this
&& child instanceof RadioButton) {
((RadioButton) child).setOnCheckedChangeListener(null);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
}
}
}
}
Here is the code adding the radio buttons to the extended radiogroup:
private void setupRadioButtonAnswers() {
ArrayList<HolderAnswer> listAnswers = GlobalVars.questionHolders[GlobalVars.arrayRowNumber]
.getListAnswers();
ArrayList<ArrayList<HolderAnswer>> listAnswersSorted = new ArrayList<ArrayList<HolderAnswer>>();
ArrayList<TableRow> alTableRows = new ArrayList<TableRow>();
int NumberInColumns = (int) Math.floor(listAnswers.size() / NUMBER_OF_COLUMNS);
// make higher number of answers on the right
if (listAnswers.size() % NUMBER_OF_COLUMNS > 0)
NumberInColumns++;
for (int i = 0; i < NumberInColumns; i++) {
TableRow row = new TableRow(this);
TableRow.LayoutParams lp = new TableRow.LayoutParams(
TableRow.LayoutParams.WRAP_CONTENT);
row.setLayoutParams(lp);
alTableRows.add(row);
}
int count = 0;
// sort by row
/*
* a[0] = "Question 1"
a[1] = "Question 2"
a[2] = "Question 3"
a[3] = "Question 4"
a[4] = "Question 5"
a[5] = "Question 6"
a[6] = "Question 7"
sorted to:
a[0] = "Question 1" a[1] = "Question 5"
a[2] = "Question 2" a[3] = "Question 6"
a[4] = "Question 3" a[5] = "Question 7"
a[6] = "Question 4"
*/
// initialize the ArrayLists in listAnswersSorted
int numRows = listAnswers.size() / NUMBER_OF_COLUMNS + 1;
for (int i = 0; i < numRows; i += 1) {
listAnswersSorted.add(new ArrayList<HolderAnswer>());
}
// calculate column index where the "step" happens
int step = listAnswers.size() % NUMBER_OF_COLUMNS;
// loop through and add elements to listAnswersSorted
int index = 0;
int row = 0;
int col = 0;
while (index < listAnswers.size()) {
listAnswersSorted.get(row).add(listAnswers.get(index));
int rows = col < step ? numRows : numRows - 1;
row += 1;
if (row == rows) {
row = 0;
col += 1;
}
index += 1;
}
row = 0;
int columncount = 1;
for (ArrayList<HolderAnswer> sortedArrayList : listAnswersSorted) {
for (HolderAnswer answer : sortedArrayList) {
final RadioButton button = new RadioButton(this);
button.setTag(answer.getRecID());
button.setId(GlobalVars.getLatestId());
button.setTextColor(Color.BLACK);
GlobalVars.setupText(con, button, answer.getTextID());
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
button.setEnabled(false);
handlerReenableView.sendEmptyMessageDelayed(button.getId(), 1000);
button.setChecked(true);
radioGroup.check(button.getId());
}
});
button.setLayoutParams(new TableRow.LayoutParams(columncount));
alTableRows.get(row).addView(button);
if (columncount==NUMBER_OF_COLUMNS) {
columncount = 1;
radioGroup.addView(alTableRows.get(row));
alTableRows.get(row).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(int k=0;k<((TableRow) v).getChildCount();k++) {
TableRow row = (TableRow) v;
for (int l=0;l<row.getChildCount();l++) {
RadioButton tableButton = (RadioButton) row.getChildAt(l);
if (tableButton.isChecked) {
radioGroup.check(tableButton.getId());
}
}
}
}
});
}
else {
columncount++;
}
//if (row=NumberInColumns)
count++;
}
if (count == listAnswers.size()) {
radioGroup.addView(alTableRows.get(row));
}
row++;
}
radioGroup.setOnCheckedChangeListener(new RadioGroupColumns.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroupColumns group, int checkedId) {
Log.d("We're here",String.valueOf(checkedId));
if (checkedId == -1) {
for (int i = 0; i < radioGroup.getChildCount(); i++) {
TableRow row = (TableRow)radioGroup.getChildAt(i);
for (int j=0;j<row.getChildCount();j++) {
if (RadioButton.class.isAssignableFrom(row.getChildAt(j).getClass())) {
((RadioButton) row.getChildAt(j)).setChecked(false);
}
}
}
} else {
for (int i = 0; i < radioGroup.getChildCount(); i++) {
TableRow row = (TableRow)radioGroup.getChildAt(i);
for (int j=0;j<row.getChildCount();j++) {
if (RadioButton.class.isAssignableFrom(row.getChildAt(j).getClass())
&& row.getChildAt(j).getId() != -1) {
((RadioButton) row.getChildAt(j)).setChecked(false);
}
}
}
RadioButton checkedRadioButton = (RadioButton) radioGroup.findViewById(checkedId);
checkedRadioButton.setChecked(true);
Log.d("checkedID onchecked Change()", String.valueOf(radioGroup.getCheckedRadioButtonId()));
}
}
});
}
I'm sure your question has been answered by now, but here is another take on it. With this code you can wrap your radio buttons into any layout you want (you don't need a radio group at all in fact). Also I would suggest using linear layouts to make the columns/rows you need.
My code is based on @infografnet and @lostdev (also thanks @Neromancer for the Compound Button suggestion!)
public class AdvRadioGroup {
public interface OnButtonCheckedListener {
void onButtonChecked(CompoundButton button);
}
private final List<CompoundButton> buttons;
private final View.OnClickListener onClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
setChecked((CompoundButton) v);
}
};
private OnButtonCheckedListener listener;
private CompoundButton lastChecked;
public AdvRadioGroup(View view) {
buttons = new ArrayList<>();
parseView(view);
}
private void parseView(final View view) {
if(view instanceof CompoundButton) {
buttons.add((CompoundButton) view);
view.setOnClickListener(onClick);
} else if(view instanceof ViewGroup) {
final ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount();i++) {
parseView(group.getChildAt(i));
}
}
}
public List<CompoundButton> getButtons() { return buttons; }
public CompoundButton getLastChecked() { return lastChecked; }
public void setChecked(int index) { setChecked(buttons.get(index)); }
public void setChecked(CompoundButton button) {
if(button == lastChecked) return;
for (CompoundButton btn : buttons) {
btn.setChecked(false);
}
button.setChecked(true);
lastChecked = button;
if(listener != null) {
listener.onButtonChecked(button);
}
}
public void setOnButtonCheckedListener(OnButtonCheckedListener listener) { this.listener = listener; }
}
Usage (with included listener):
AdvRadioGroup group = new AdvRadioGroup(findViewById(R.id.YOUR_VIEW));
group.setOnButtonCheckedListener(new AdvRadioGroup.OnButtonCheckedListener() {
@Override
public void onButtonChecked(CompoundButton button) {
// do fun stuff here!
}
});
Bonus: You can get the last checked button, the list of entire buttons, and you can check any button by index with this!