How to group a 3x3 grid of radio buttons?
Actually it's not that hard if you subclass TableLayout
like in this example
/** * */package com.codtech.android.view;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.RadioButton;import android.widget.TableLayout;import android.widget.TableRow;/** * @author diego * */public class ToggleButtonGroupTableLayout extends TableLayout implements OnClickListener { private static final String TAG = "ToggleButtonGroupTableLayout"; private RadioButton activeRadioButton; /** * @param context */ public ToggleButtonGroupTableLayout(Context context) { super(context); // TODO Auto-generated constructor stub } /** * @param context * @param attrs */ public ToggleButtonGroupTableLayout(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override public void onClick(View v) { final RadioButton rb = (RadioButton) v; if ( activeRadioButton != null ) { activeRadioButton.setChecked(false); } rb.setChecked(true); activeRadioButton = rb; } /* (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; }}
and create a layout like this (of course you need to clean it up but you got the idea)
<?xml version="1.0" encoding="utf-8"?><com.codtech.android.view.ToggleButtonGroupTableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/radGroup1"> <TableRow> <RadioButton android:id="@+id/rad1" android:text="Button1" android:layout_width="105px" android:layout_height="wrap_content" android:textSize="13px" /> <RadioButton android:id="@+id/rad2" android:text="Button2" android:layout_width="105px" android:textSize="13px" android:layout_height="wrap_content" /> <RadioButton android:id="@+id/rad3" android:text="Button3" android:layout_width="105px" android:textSize="13px" android:layout_height="wrap_content" /> </TableRow> <TableRow> <RadioButton android:id="@+id/rad1" android:text="Button1" android:layout_width="105px" android:layout_height="wrap_content" android:textSize="13px" /> <RadioButton android:id="@+id/rad2" android:text="Button2" android:layout_width="105px" android:textSize="13px" android:layout_height="wrap_content" /> <RadioButton android:id="@+id/rad3" android:text="Button3" android:layout_width="105px" android:textSize="13px" android:layout_height="wrap_content" /> </TableRow> <TableRow> <RadioButton android:id="@+id/rad1" android:text="Button1" android:layout_width="105px" android:layout_height="wrap_content" android:textSize="13px" /> <RadioButton android:id="@+id/rad2" android:text="Button2" android:layout_width="105px" android:textSize="13px" android:layout_height="wrap_content" /> <RadioButton android:id="@+id/rad3" android:text="Button3" android:layout_width="105px" android:textSize="13px" android:layout_height="wrap_content" /> </TableRow></com.codtech.android.view.ToggleButtonGroupTableLayout>
After above https://stackoverflow.com/a/2383978/5567009 answer I got another solution for this question, I added some other functionality like, to save the state of the group and also functionality to clear the check functionality like in radio group.
import android.content.Context;import android.os.Parcel;import android.os.Parcelable;import android.support.annotation.IdRes;import android.util.AttributeSet;import android.view.View;import android.widget.RadioButton;import android.widget.TableLayout;import android.widget.TableRow;public class RadioGridGroup extends TableLayout implements View.OnClickListener { private static final String TAG = "ToggleButtonGroupTableLayout"; private int checkedButtonID = -1; /** * @param context */ public RadioGridGroup(Context context) { super(context); // TODO Auto-generated constructor stub } /** * @param context * @param attrs */ public RadioGridGroup(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } @Override public void onClick(View v) { if (v instanceof RadioButton) { int id = v.getId(); check(id); } } private void setCheckedStateForView(int viewId, boolean checked) { View checkedView = findViewById(viewId); 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); } } } /** * @return the checked button Id */ public int getCheckedRadioButtonId() { return checkedButtonID; } /** * Check the id * * @param id */ public void check(@IdRes int id) { // don't even bother if (id != -1 && (id == checkedButtonID)) { return; } if (checkedButtonID != -1) { setCheckedStateForView(checkedButtonID, false); } if (id != -1) { setCheckedStateForView(id, true); } setCheckedId(id); } /** * set the checked button Id * * @param id */ private void setCheckedId(int id) { this.checkedButtonID = id; } public void clearCheck() { check(-1); } @Override protected void onRestoreInstanceState(Parcelable state) { if (!(state instanceof SavedState)) { super.onRestoreInstanceState(state); return; } SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); this.checkedButtonID = ss.buttonId; setCheckedStateForView(checkedButtonID, true); } @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.buttonId = checkedButtonID; return savedState; } static class SavedState extends BaseSavedState { int buttonId; /** * Constructor used when reading from a parcel. Reads the state of the superclass. * * @param source */ public SavedState(Parcel source) { super(source); buttonId = source.readInt(); } /** * Constructor called by derived classes when creating their SavedState objects * * @param superState The state of the superclass of this view */ public SavedState(Parcelable superState) { super(superState); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeInt(buttonId); } public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; }}
and use this in XML as follows
<com.test.customviews.RadioGridGroup xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TableRow android:layout_marginTop="@dimen/preview_five"> <RadioButton android:id="@+id/rad1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button1" /> <RadioButton android:id="@+id/rad2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button2" /> </TableRow> <TableRow android:layout_marginTop="@dimen/preview_five"> <RadioButton android:id="@+id/rad3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button3" /> <RadioButton android:id="@+id/rad4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button4" /> </TableRow> <TableRow android:layout_marginTop="@dimen/preview_five"> <RadioButton android:id="@+id/rad5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button5" /> <RadioButton android:id="@+id/rad6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button6" /> </TableRow> <TableRow android:layout_marginTop="@dimen/preview_five"> <RadioButton android:id="@+id/rad7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button7" /> <RadioButton android:id="@+id/rad8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button8" /> </TableRow></com.test.customviews.RadioGridGroup>
For any other improvements, please comment.
This uses a custom GridLayout with the RadioGroup functionality. Thanks to Saikrishnan Ranganathan for saiaspire/RadioGridGroup
<com.sample.RadioGridGroup xmlns:grid="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="wrap_content" grid:columnCount="3" grid:useDefaultMargins="true"> <android.support.v7.widget.AppCompatRadioButton android:checked="true" android:text="Text1" grid:layout_columnWeight="1"/> <android.support.v7.widget.AppCompatRadioButton android:text="Text2" grid:layout_columnWeight="1"/> <android.support.v7.widget.AppCompatRadioButton android:text="Text3" grid:layout_columnWeight="1"/> <android.support.v7.widget.AppCompatRadioButton android:text="Text4" grid:layout_columnWeight="1"/> <android.support.v7.widget.AppCompatRadioButton android:text="Text5" grid:layout_columnWeight="1"/> <android.support.v7.widget.AppCompatRadioButton android:text="Text6" grid:layout_columnWeight="1"/> <android.support.v7.widget.AppCompatRadioButton android:text="Text7" grid:layout_columnWeight="1"/> <android.support.v7.widget.AppCompatRadioButton android:text="Text8" grid:layout_columnWeight="1"/> <android.support.v7.widget.AppCompatRadioButton android:text="Text9" grid:layout_columnWeight="1"/> </com.sample.RadioGridGroup>