How to group RadioButton from different LinearLayouts?

I was wondering if it is possible to group each single RadioButton in a unique RadioGroup maintaining the same structure. My structure looks like this:

  • LinearLayout_main
    • LinearLayout_1
      • RadioButton1
    • LinearLayout_2
      • RadioButton2
    • LinearLayout_3
      • RadioButton3

As you can see, now each RadioButton is a different LinearLayout . I tried using the structure below, but it does not work:

  • Radiogroup
    • LinearLayout_main
      • LinearLayout_1
        • RadioButton1
      • LinearLayout_2
        • RadioButton2
      • LinearLayout_3
        • RadioButton3
+79
android radio-button android-linearlayout radio-group
May 05 '12 at 10:34
source share
19 answers

It seems that the good people on Google / Android are suggesting that when using RadioButtons you don't need the flexibility that comes with every other aspect of the Android UI / layout system. Simply put: they don’t want you to insert layouts and switches. Sigh.

So you need to solve this problem. This means that you must use the switches yourself.

It really is not too complicated. In your onCreate (), set your RadioButtons with your onClick () so that when activated they set CheckCheck (true) and do the opposite for the other buttons. For example:

 class FooActivity { RadioButton m_one, m_two, m_three; @Override protected void onCreate(Bundle savedInstanceState) { ... m_one = (RadioButton) findViewById(R.id.first_radio_button); m_two = (RadioButton) findViewById(R.id.second_radio_button); m_three = (RadioButton) findViewById(R.id.third_radio_button); m_one.setOnClickListener(new OnClickListener() { public void onClick(View v) { m_one.setChecked(true); m_two.setChecked(false); m_three.setChecked(false); } }); m_two.setOnClickListener(new OnClickListener() { public void onClick(View v) { m_one.setChecked(false); m_two.setChecked(true); m_three.setChecked(false); } }); m_three.setOnClickListener(new OnClickListener() { public void onClick(View v) { m_one.setChecked(false); m_two.setChecked(false); m_three.setChecked(true); } }); ... } // onCreate() } 

Yes, I know - the old school way. But it does work. Good luck

+40
Nov 07 '12 at 16:25
source share

Use this class that I created. He will find all verified children in your hierarchy.

 import java.util.ArrayList; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.Checkable; import android.widget.LinearLayout; public class MyRadioGroup extends LinearLayout { private ArrayList<View> mCheckables = new ArrayList<View>(); public MyRadioGroup(Context context) { super(context); } public MyRadioGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyRadioGroup(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) { super.addView(child, index, params); parseChild(child); } public void parseChild(final View child) { if(child instanceof Checkable) { mCheckables.add(child); child.setOnClickListener(new OnClickListener() { public void onClick(View v) { for(int i = 0; i < mCheckables.size();i++) { Checkable view = (Checkable) mCheckables.get(i); if(view == v) { ((Checkable)view).setChecked(true); } else { ((Checkable)view).setChecked(false); } } } }); } else if(child instanceof ViewGroup) { parseChildren((ViewGroup)child); } } public void parseChildren(final ViewGroup child) { for (int i = 0; i < child.getChildCount();i++) { parseChild(child.getChildAt(i)); } } } 
+26
Jan 13
source share

Well, I wrote this simple class.

Just use it like this:

 // add any number of RadioButton resource IDs here GRadioGroup gr = new GRadioGroup(this, R.id.radioButton1, R.id.radioButton2, R.id.radioButton3); 

or

 GRadioGroup gr = new GRadioGroup(rb1, rb2, rb3); // where RadioButton rb1 = (RadioButton) findViewById(R.id.radioButton1); // etc. 

You can call it in onCreate () Activity, for example. No matter which RadioButton you click, the rest will be disabled. In addition, it does not matter if some of the RadioButtons are inside some RadioGroup or not.

Here's the class:

 package pl.infografnet.GClasses; import java.util.ArrayList; import java.util.List; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewParent; import android.widget.RadioButton; import android.widget.RadioGroup; public class GRadioGroup { List<RadioButton> radios = new ArrayList<RadioButton>(); /** * Constructor, which allows you to pass number of RadioButton instances, * making a group. * * @param radios * One RadioButton or more. */ public GRadioGroup(RadioButton... radios) { super(); for (RadioButton rb : radios) { this.radios.add(rb); rb.setOnClickListener(onClick); } } /** * Constructor, which allows you to pass number of RadioButtons * represented by resource IDs, making a group. * * @param activity * Current View (or Activity) to which those RadioButtons * belong. * @param radiosIDs * One RadioButton or more. */ public GRadioGroup(View activity, int... radiosIDs) { super(); for (int radioButtonID : radiosIDs) { RadioButton rb = (RadioButton)activity.findViewById(radioButtonID); if (rb != null) { this.radios.add(rb); rb.setOnClickListener(onClick); } } } /** * This occurs everytime when one of RadioButtons is clicked, * and deselects all others in the group. */ OnClickListener onClick = new OnClickListener() { @Override public void onClick(View v) { // let deselect all radios in group for (RadioButton rb : radios) { ViewParent p = rb.getParent(); if (p.getClass().equals(RadioGroup.class)) { // if RadioButton belongs to RadioGroup, // then deselect all radios in it RadioGroup rg = (RadioGroup) p; rg.clearCheck(); } else { // if RadioButton DOES NOT belong to RadioGroup, // just deselect it rb.setChecked(false); } } // now let select currently clicked RadioButton if (v.getClass().equals(RadioButton.class)) { RadioButton rb = (RadioButton) v; rb.setChecked(true); } } }; } 
+17
Apr 17 '13 at 22:35
source share

Here is my solution based on @lostdev solution and RadioGroup implementation. This is a RadioGroup modified to work with RadioButton (or other CompoundButtons) that are nested in child layouts.

 import android.content.Context; import android.os.Build; import android.support.annotation.IdRes; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.LinearLayout; import android.widget.RadioButton; import java.util.concurrent.atomic.AtomicInteger; /** * This class is a replacement for android RadioGroup - it supports * child layouts which standard RadioGroup doesn't. */ public class RecursiveRadioGroup extends LinearLayout { public interface OnCheckedChangeListener { void onCheckedChanged(RecursiveRadioGroup group, @IdRes int checkedId); } /** * For generating unique view IDs on API < 17 with {@link #generateViewId()}. */ private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); private CompoundButton checkedView; private CompoundButton.OnCheckedChangeListener childOnCheckedChangeListener; /** * When this flag is true, onCheckedChangeListener discards events. */ private boolean mProtectFromCheckedChange = false; private OnCheckedChangeListener onCheckedChangeListener; private PassThroughHierarchyChangeListener mPassThroughListener; public RecursiveRadioGroup(Context context) { super(context); setOrientation(HORIZONTAL); init(); } public RecursiveRadioGroup(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public RecursiveRadioGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { childOnCheckedChangeListener = new CheckedStateTracker(); mPassThroughListener = new PassThroughHierarchyChangeListener(); super.setOnHierarchyChangeListener(mPassThroughListener); } @Override public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { mPassThroughListener.mOnHierarchyChangeListener = listener; } @Override protected void onFinishInflate() { super.onFinishInflate(); // checks the appropriate radio button as requested in the XML file if (checkedView != null) { mProtectFromCheckedChange = true; setCheckedStateForView(checkedView, true); mProtectFromCheckedChange = false; setCheckedView(checkedView); } } @Override public void addView(View child, int index, ViewGroup.LayoutParams params) { parseChild(child); super.addView(child, index, params); } private void parseChild(final View child) { if (child instanceof CompoundButton) { final CompoundButton checkable = (CompoundButton) child; if (checkable.isChecked()) { mProtectFromCheckedChange = true; if (checkedView != null) { setCheckedStateForView(checkedView, false); } mProtectFromCheckedChange = false; setCheckedView(checkable); } } else if (child instanceof ViewGroup) { parseChildren((ViewGroup) child); } } private void parseChildren(final ViewGroup child) { for (int i = 0; i < child.getChildCount(); i++) { parseChild(child.getChildAt(i)); } } /** * <p>Sets the selection to the radio button whose identifier is passed in * parameter. Using -1 as the selection identifier clears the selection; * such an operation is equivalent to invoking {@link #clearCheck()}.</p> * * @param view the radio button to select in this group * @see #getCheckedItemId() * @see #clearCheck() */ public void check(CompoundButton view) { if(checkedView != null) { setCheckedStateForView(checkedView, false); } if(view != null) { setCheckedStateForView(view, true); } setCheckedView(view); } private void setCheckedView(CompoundButton view) { checkedView = view; if(onCheckedChangeListener != null) { onCheckedChangeListener.onCheckedChanged(this, checkedView.getId()); } } private void setCheckedStateForView(View checkedView, boolean checked) { if (checkedView != null && checkedView instanceof CompoundButton) { ((CompoundButton) checkedView).setChecked(checked); } } /** * <p>Returns the identifier of the selected radio button in this group. * Upon empty selection, the returned value is -1.</p> * * @return the unique id of the selected radio button in this group * @attr ref android.R.styleable#RadioGroup_checkedButton * @see #check(CompoundButton) * @see #clearCheck() */ @IdRes public int getCheckedItemId() { return checkedView.getId(); } public CompoundButton getCheckedItem() { return checkedView; } /** * <p>Clears the selection. When the selection is cleared, no radio button * in this group is selected and {@link #getCheckedItemId()} returns * null.</p> * * @see #check(CompoundButton) * @see #getCheckedItemId() */ public void clearCheck() { check(null); } /** * <p>Register a callback to be invoked when the checked radio button * changes in this group.</p> * * @param listener the callback to call on checked state change */ public void setOnCheckedChangeListener(RecursiveRadioGroup.OnCheckedChangeListener listener) { onCheckedChangeListener = listener; } /** * Generate a value suitable for use in {@link #setId(int)}. * This value will not collide with ID values generated at build time by aapt for R.id. * * @return a generated ID value */ public static int generateViewId() { for (; ; ) { final int result = sNextGeneratedId.get(); // aapt-generated IDs have the high byte nonzero; clamp to the range under that. int newValue = result + 1; if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. if (sNextGeneratedId.compareAndSet(result, newValue)) { return result; } } } private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener { @Override public void onCheckedChanged(CompoundButton view, boolean b) { if (mProtectFromCheckedChange) { return; } mProtectFromCheckedChange = true; if (checkedView != null) { setCheckedStateForView(checkedView, false); } mProtectFromCheckedChange = false; int id = view.getId(); setCheckedView(view); } } private class PassThroughHierarchyChangeListener implements OnHierarchyChangeListener { private OnHierarchyChangeListener mOnHierarchyChangeListener; @Override public void onChildViewAdded(View parent, View child) { if (child instanceof CompoundButton) { int id = child.getId(); if (id == View.NO_ID) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { child.setId(generateViewId()); } else { child.setId(View.generateViewId()); } } ((CompoundButton) child).setOnCheckedChangeListener(childOnCheckedChangeListener); if (mOnHierarchyChangeListener != null) { mOnHierarchyChangeListener.onChildViewAdded(parent, child); } } else if(child instanceof ViewGroup) { // View hierarchy seems to be constructed from the bottom up, // so all child views are already added. That why we // manually call the listener for all children of ViewGroup. for(int i = 0; i < ((ViewGroup) child).getChildCount(); i++) { onChildViewAdded(child, ((ViewGroup) child).getChildAt(i)); } } } @Override public void onChildViewRemoved(View parent, View child) { if (child instanceof RadioButton) { ((CompoundButton) child).setOnCheckedChangeListener(null); } if (mOnHierarchyChangeListener != null) { mOnHierarchyChangeListener.onChildViewRemoved(parent, child); } } } } 

You can use it in the layout in the same way as a regular RadioGroup , except that it works with nested RadioButton views:

 <RecursiveRadioGroup android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:layout_marginBottom="16dp" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:orientation="horizontal"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical"> <RadioButton android:id="@+id/rbNotEnoughProfileInfo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Not enough profile information"/> <RadioButton android:id="@+id/rbNotAGoodFit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Not a good fit"/> <RadioButton android:id="@+id/rbDatesNoLongerAvailable" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Dates no longer available"/> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical"> <RadioButton android:id="@+id/rbOther" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Other"/> <android.support.v7.widget.AppCompatEditText android:id="@+id/etReason" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/tvMessageError" android:textSize="15sp" android:gravity="top|left" android:hint="Tell us more" android:padding="16dp" android:background="@drawable/edit_text_multiline_background"/> </LinearLayout> </RecursiveRadioGroup> 
+7
Mar 22 '18 at 11:46
source share

Sigh .. It’s really to blame that Android does not have such basic functionality.

Adapted from @ScottBiggs answer, here is probably the shortest way to do this with Kotlin:

 var currentSelected = button1 listOf<RadioButton>( button1, button2, button3, ... ).forEach { it.setOnClickListener { _ -> currentSelected.isChecked = false currentSelected = it currentSelected.isChecked = true } } 
+4
Aug 08 '18 at 18:50
source share

I created these two methods to solve this problem. All you have to do is pass the ViewGroup where the RadioButtons (maybe RadioGroup, LinearLayout, RelativeLayout, etc.), and it sets the OnClick events exclusively, that is, when one of the RadioButtons is a child of the ViewGroup (on any nested level), the rest are not selected. It works with as many nested layouts as you would like.

 public class Utils { public static void setRadioExclusiveClick(ViewGroup parent) { final List<RadioButton> radios = getRadioButtons(parent); for (RadioButton radio: radios) { radio.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { RadioButton r = (RadioButton) v; r.setChecked(true); for (RadioButton r2:radios) { if (r2.getId() != r.getId()) { r2.setChecked(false); } } } }); } } private static List<RadioButton> getRadioButtons(ViewGroup parent) { List<RadioButton> radios = new ArrayList<RadioButton>(); for (int i=0;i < parent.getChildCount(); i++) { View v = parent.getChildAt(i); if (v instanceof RadioButton) { radios.add((RadioButton) v); } else if (v instanceof ViewGroup) { List<RadioButton> nestedRadios = getRadioButtons((ViewGroup) v); radios.addAll(nestedRadios); } } return radios; } } 

Use within an action will be as follows:

 ViewGroup parent = findViewById(R.id.radios_parent); Utils.setRadioExclusiveClick(parent); 
+3
Nov 16 '14 at 20:04
source share

I wrote my own class of radio groups, which allows you to contain nested radio buttons. Check this. If you find errors, let me know.

 import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.LinearLayout; /** * This class is used to create a multiple-exclusion scope for a set of compound * buttons. Checking one compound button that belongs to a group unchecks any * previously checked compound button within the same group. Intially, all of * the compound buttons are unchecked. While it is not possible to uncheck a * particular compound button, the group can be cleared to remove the checked * state. Basically, this class extends functionality of * {@link android.widget.RadioGroup} because it doesn't require that compound * buttons are direct childs of the group. This means you can wrap compound * buttons with other views. <br> * <br> * * <b>IMPORTATNT! Follow these instruction when using this class:</b><br> * 1. Each direct child of this group must contain one compound button or be * compound button itself.<br> * 2. Do not set any "on click" or "on checked changed" listeners for the childs * of this group. */ public class CompoundButtonsGroup extends LinearLayout { private View checkedView; private OnCheckedChangeListener listener; private OnHierarchyChangeListener onHierarchyChangeListener; private OnHierarchyChangeListener onHierarchyChangeListenerInternal = new OnHierarchyChangeListener() { @Override public final void onChildViewAdded(View parent, View child) { notifyHierarchyChanged(null); if (CompoundButtonsGroup.this.onHierarchyChangeListener != null) { CompoundButtonsGroup.this.onHierarchyChangeListener.onChildViewAdded( parent, child); } } @Override public final void onChildViewRemoved(View parent, View child) { notifyHierarchyChanged(child); if (CompoundButtonsGroup.this.onHierarchyChangeListener != null) { CompoundButtonsGroup.this.onHierarchyChangeListener.onChildViewRemoved( parent, child); } } }; public CompoundButtonsGroup(Context context) { super(context); init(); } public CompoundButtonsGroup(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CompoundButtonsGroup(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { super.setOnHierarchyChangeListener(this.onHierarchyChangeListenerInternal); } @Override public final void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { this.onHierarchyChangeListener = listener; } /** * Register a callback to be invoked when the checked view changes in this * group. * * @param listener * the callback to call on checked state change. */ public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { this.listener = listener; } /** * Returns currently selected view in this group. Upon empty selection, the * returned value is null. */ public View getCheckedView() { return this.checkedView; } /** * Returns index of currently selected view in this group. Upon empty * selection, the returned value is -1. */ public int getCheckedViewIndex() { return (this.checkedView != null) ? indexOfChild(this.checkedView) : -1; } /** * Sets the selection to the view whose index in group is passed in * parameter. * * @param index * the index of the view to select in this group. */ public void check(int index) { check(getChildAt(index)); } /** * Clears the selection. When the selection is cleared, no view in this * group is selected and {@link #getCheckedView()} returns null. */ public void clearCheck() { if (this.checkedView != null) { findCompoundButton(this.checkedView).setChecked(false); this.checkedView = null; onCheckedChanged(); } } private void onCheckedChanged() { if (this.listener != null) { this.listener.onCheckedChanged(this.checkedView); } } private void check(View child) { if (this.checkedView == null || !this.checkedView.equals(child)) { if (this.checkedView != null) { findCompoundButton(this.checkedView).setChecked(false); } CompoundButton comBtn = findCompoundButton(child); comBtn.setChecked(true); this.checkedView = child; onCheckedChanged(); } } private void notifyHierarchyChanged(View removedView) { for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { check(v); } }); CompoundButton comBtn = findCompoundButton(child); comBtn.setClickable(comBtn.equals(child)); } if (this.checkedView != null && removedView != null && this.checkedView.equals(removedView)) { clearCheck(); } } private CompoundButton findCompoundButton(View view) { if (view instanceof CompoundButton) { return (CompoundButton) view; } if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { CompoundButton compoundBtn = findCompoundButton(((ViewGroup) view) .getChildAt(i)); if (compoundBtn != null) { return compoundBtn; } } } return null; } /** * Interface definition for a callback to be invoked when the checked view * changed in this group. */ public interface OnCheckedChangeListener { /** * Called when the checked view has changed. * * @param checkedView * newly checked view or null if selection was cleared in the * group. */ public void onCheckedChanged(View checkedView); } } 
+2
Oct 11 '13 at 14:27
source share

You need to do two things:

  • Use mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
  • Make your custom view representation of the string Checkable .

Therefore, I believe that the best solution is to implement Checkable inside your LinearLayout: (thanks to daichan4649, at his link, https://gist.github.com/daichan4649/5245378 , I took all the code inserted below)

CheckableLayout.java

 package daichan4649.test; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.Checkable; import android.widget.LinearLayout; public class CheckableLayout extends LinearLayout implements Checkable { private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked }; public CheckableLayout(Context context) { super(context, null); } public CheckableLayout(Context context, AttributeSet attrs) { super(context, attrs, 0); } public CheckableLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } private boolean checked; @Override public boolean isChecked() { return checked; } @Override public void setChecked(boolean checked) { if (this.checked != checked) { this.checked = checked; refreshDrawableState(); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); if (child instanceof Checkable) { ((Checkable) child).setChecked(checked); } } } } @Override public void toggle() { setChecked(!checked); } @Override protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } } 

inflater_list_column.xml

 <?xml version="1.0" encoding="utf-8"?> <daichan4649.test.CheckableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/check_area" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical"> <TextView android:id="@+id/text" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_weight="1" android:gravity="center_vertical" /> <RadioButton android:id="@+id/radio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:focusable="false" android:focusableInTouchMode="false" /> </daichan4649.test.CheckableLayout> 

TestFragment.java

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_test, container, false); // 表示データList<String> dataList = new ArrayList<String>(); // 初期選択位置int initSelectedPosition = 3; // リスト設定TestAdapter adapter = new TestAdapter(getActivity(), dataList); ListView listView = (ListView) view.findViewById(R.id.list); listView.setAdapter(adapter); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); listView.setItemChecked(initSelectedPosition, true); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 選択状態を要素(checkable)へ反映Checkable child = (Checkable) parent.getChildAt(position); child.toggle(); } }); return view; } private static class TestAdapter extends ArrayAdapter<String> { private LayoutInflater inflater; public TestAdapter(Context context, List<String> dataList) { super(context, 0, dataList); inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(int position, View convertView, ViewGroup parent) { final ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.inflater_list_column, null); holder = new ViewHolder(); holder.text = (TextView) convertView.findViewById(R.id.text); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // bindData holder.text.setText(getItem(position)); return convertView; } } private static class ViewHolder { TextView text; } 
+2
Feb 26 '15 at 21:44
source share

Nothing prevents you from implementing this layout structure ( RadioGroup is actually a subclass of LinearLayout ), but you shouldn't. First of all, you create a level 4 structure in depth (using a different layout structure that you can optimize), and secondly, if your RadioButtons are not direct children of RadioGroup , the only element selected in the group will not work. This means that if you select Radiobutton from this layout and then select another Radiobutton , you will get two RadioButtons instead of the last one selected.

If you explain what you want to do in this layout, I can recommend an alternative for you.

+1
May 5 '12 at 10:53
source share

I have a problem with the same problem as I want to place 4 different switches in two different linearlayout, and this layout will be a child of the radio group. To achieve desire behavior in RadioGroup, I overloaded the addView function

Here is the solution

 public class AgentRadioGroup extends RadioGroup { public AgentRadioGroup(Context context) { super(context); } public AgentRadioGroup(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void onViewAdded(View child) { if( child instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) child; for(int i=0; i<viewGroup.getChildCount(); i++) { View subChild = viewGroup.getChildAt(i); if( subChild instanceof ViewGroup ) { onViewAdded(subChild); } else { if (subChild instanceof RadioButton) { super.onViewAdded(subChild); } } } } if (child instanceof RadioButton) { super.onViewAdded(child); } } } 
+1
Apr 21 '17 at 9:39 on
source share

This solution was not published as follows:

Step 0: Create a global variable CompountButton previousCheckedCompoundButton; .

Step 1: Create an OnCheckedChangedListener for the Radio Button

 CompoundButton.OnCheckedChangeListener onRadioButtonCheckedListener = new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (!isChecked) return; if (previousCheckedCompoundButton != null) { previousCheckedCompoundButton.setChecked(false); previousCheckedCompoundButton = buttonView; } else { previousCheckedCompoundButton = buttonView; } } }; 

Step 3: add a listener to all the switches:

 radioButton1.setOnCheckedChangeListener(onRadioButtonCheckedListener); radioButton2.setOnCheckedChangeListener(onRadioButtonCheckedListener); radioButton3.setOnCheckedChangeListener(onRadioButtonCheckedListener); radioButton4.setOnCheckedChangeListener(onRadioButtonCheckedListener); 

Here it is! your done.

+1
May 2 '17 at 10:28
source share

My $ 0.02 based on @infografnet and @lostdev (also thanks @Neromancer for suggesting the Compound button!)

 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 listener on):

 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 marked button, a list of whole buttons, and you can check any button by index using this!

+1
Aug 03 '17 at 7:08 on
source share

While this is perhaps an older topic, I would like to quickly share the simple hacked code that I wrote .. Its not for everyone and could be done with some refinement as well.

Situation for using this code
This code is for people who have a layout of the original question or the like, in my case it was as shown below. , .

  • LinLayout_Main
    • LinLayout_Row1
      • ImageView
      • RadioButton
    • LinLayout_Row2
      • ImageView
      • RadioButton
    • LinLayout_Row3
      • ImageView
      • RadioButton

?
- Child "LinLayout_Main", , "LinearLayout", RadioButtons.

"LinLayout_Main" RadioButtons, LinearLayouts.

MyMethod_ShowDialog
XML, , "setOnClickListener" RadioButton.

MyMethod_ClickRadio
RadioButton "MyMethod_ShowDialog", "setOnClickListener" "setChecked (false)" RadioButton, , "setChecked (false)" RadioButton, click.

 public void MyMethod_ShowDialog(final double tmpLat, final double tmpLng) { final Dialog dialog = new Dialog(actMain); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(R.layout.layout_dialogXML); final LinearLayout tmpLayMain = (LinearLayout)dialog.findViewById(R.id.LinLayout_Main); if (tmpLayMain!=null) { // Perform look for each child of main LinearLayout int iChildCount1 = tmpLayMain.getChildCount(); for (int iLoop1=0; iLoop1 < iChildCount1; iLoop1++){ View tmpChild1 = tmpLayMain.getChildAt(iLoop1); if (tmpChild1 instanceof LinearLayout) { // Perform look for each LinearLayout child of main LinearLayout int iChildCount2 = ((LinearLayout) tmpChild1).getChildCount(); for (int iLoop2=0; iLoop2 < iChildCount2; iLoop2++){ View tmpChild2 = ((LinearLayout) tmpChild1).getChildAt(iLoop2); if (tmpChild2 instanceof RadioButton) { ((RadioButton) tmpChild2).setOnClickListener(new RadioButton.OnClickListener() { public void onClick(View v) { MyMethod_ClickRadio(v, dialog); } }); } } } } Button dialogButton = (Button)dialog.findViewById(R.id.LinLayout_Save); dialogButton.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { dialog.dismiss(); } }); } dialog.show(); } public void MyMethod_ClickRadio(View vRadio, final Dialog dDialog) { final LinearLayout tmpLayMain = (LinearLayout)dDialog.findViewById(R.id.LinLayout_Main); if (tmpLayMain!=null) { int iChildCount1 = tmpLayMain.getChildCount(); for (int iLoop1=0; iLoop1 < iChildCount1; iLoop1++){ View tmpChild1 = tmpLayMain.getChildAt(iLoop1); if (tmpChild1 instanceof LinearLayout) { int iChildCount2 = ((LinearLayout) tmpChild1).getChildCount(); for (int iLoop2=0; iLoop2 < iChildCount2; iLoop2++){ View tmpChild2 = ((LinearLayout) tmpChild1).getChildAt(iLoop2); if (tmpChild2 instanceof RadioButton) { ((RadioButton) tmpChild2).setChecked(false); } } } } } ((RadioButton) vRadio).setChecked(true); } 

, Voids/XML/ID

, , .

0
04 . '14 3:47
source share

@Infografnet. .

RadioGroupHelper group = new RadioGroupHelper(this,R.id.radioButton1,R.id.radioButton2); group.radioButtons.get(0).performClick();//programmatically

 package com.qamar4p.farmer.ui.custom; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.view.View; import android.widget.CompoundButton; import android.widget.RadioButton; public class RadioGroupHelper { public List<CompoundButton> radioButtons = new ArrayList<>(); public RadioGroupHelper(RadioButton... radios) { super(); for (RadioButton rb : radios) { add(rb); } } public RadioGroupHelper(Activity activity, int... radiosIDs) { this(activity.findViewById(android.R.id.content),radiosIDs); } public RadioGroupHelper(View rootView, int... radiosIDs) { super(); for (int radioButtonID : radiosIDs) { add((RadioButton)rootView.findViewById(radioButtonID)); } } private void add(CompoundButton button){ this.radioButtons.add(button); button.setOnClickListener(onClickListener); } View.OnClickListener onClickListener = v -> { for (CompoundButton rb : radioButtons) { if(rb != v) rb.setChecked(false); } }; } 
0
23 . '17 at 7:13
source share

, . .

 import android.widget.RadioButton class SimpleRadioGroup(private val radioButtons: List<RadioButton>) { init { radioButtons.forEach { it.setOnClickListener { clickedButton -> radioButtons.forEach { it.isChecked = false } (clickedButton as RadioButton).isChecked = true } } } val checkedButton: RadioButton? get() = radioButtons.firstOrNull { it.isChecked } } 

- onCreate onViewCreated:

 SimpleRadioGroup(listOf(radio_button_1, radio_button_2, radio_button_3)) 
0
18 . '19 0:10
source share

Kotlin RadioButton .

 tipInfoContainerFirst.radioButton.isChecked = true var prevSelected = tipInfoContainerFirst.radioButton prevSelected.isSelected = true listOf<RadioButton>( tipInfoContainerFirst.radioButton, tipInfoContainerSecond.radioButton, tipInfoContainerThird.radioButton, tipInfoContainerForth.radioButton, tipInfoContainerCustom.radioButton ).forEach { it.setOnClickListener { _it -> if(!it.isSelected) { prevSelected.isChecked = false prevSelected.isSelected = false it.radioButton.isSelected = true prevSelected = it.radioButton } } } 
0
27 . '19 4:11
source share
  int currentCheckedRadioButton = 0; int[] myRadioButtons= new int[6]; myRadioButtons[0] = R.id.first; myRadioButtons[1] = R.id.second; //.. for (int radioButtonID : myRadioButtons) { findViewById(radioButtonID).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (currentCheckedRadioButton != 0) ((RadioButton) findViewById(currentCheckedRadioButton)).setChecked(false); currentCheckedRadioButton = v.getId(); } }); } 
0
09 '19 0:42
source share

, , , .

XML :

 <RadioGroup android:layout_marginTop="40dp" android:layout_marginEnd="23dp" android:id="@+id/rgGender" android:layout_width="match_parent" android:layout_below="@id/tvCustomer" android:orientation="horizontal" android:layout_height="wrap_content"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center_horizontal" android:layout_weight="1"> <RadioButton android:id="@+id/rbMale" android:layout_width="80dp" android:layout_height="60dp" android:background="@drawable/male_radio_btn_selector" android:button="@null" style="@style/RadioButton.Roboto.20sp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Male" style="@style/TextView.RobotoLight.TxtGrey.18sp" android:layout_margin="0dp" android:textSize="@dimen/txtsize_20sp"/> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center_horizontal" android:layout_weight="1"> <RadioButton android:layout_weight="1" android:gravity="center" android:id="@+id/rbFemale" android:layout_width="80dp" android:layout_height="60dp" android:button="@null" android:background="@drawable/female_radio_btn_selector" style="@style/RadioButton.Roboto.20sp" android:textColor="@color/light_grey"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Female" android:layout_margin="0dp" style="@style/TextView.RobotoLight.TxtGrey.18sp" android:textSize="@dimen/txtsize_20sp"/> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center_horizontal" android:layout_weight="1"> <RadioButton android:layout_weight="1" android:gravity="center" android:id="@+id/rbOthers" android:layout_width="80dp" android:layout_height="60dp" android:button="@null" android:background="@drawable/other_gender_radio_btn_selector" style="@style/RadioButton.Roboto.20sp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Other" android:layout_margin="0dp" style="@style/TextView.RobotoLight.TxtGrey.18sp" android:textSize="@dimen/txtsize_20sp"/> </LinearLayout> </RadioGroup> 

Java: setOnCheckedChangeListener 3 , , .

 @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { switch (compoundButton.getId()){ case R.id.rbMale: if(rbMale.isChecked()){ rbMale.setChecked(true); rbFemale.setChecked(false); rbOther.setChecked(false); } break; case R.id.rbFemale: if(rbFemale.isChecked()){ rbMale.setChecked(false); rbFemale.setChecked(true); rbOther.setChecked(false); } break; case R.id.rbOthers: if(rbOther.isChecked()){ rbMale.setChecked(false); rbFemale.setChecked(false); rbOther.setChecked(true); } break; } } 
0
17 . '19 13:59
source share

RadioGroup LinearLayout .

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <RadioGroup android:id="@+id/radioGroup1" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:weightSum="1" > <RadioButton android:id="@+id/radio0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="RadioButton" /> <RadioButton android:id="@+id/radio1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioButton" /> <RadioButton android:id="@+id/radio2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioButton" /> </RadioGroup> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <RadioGroup android:id="@+id/radioGroup2" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:weightSum="1" > <RadioButton android:id="@+id/radio3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="RadioButton" /> <RadioButton android:id="@+id/radio4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioButton" /> <RadioButton android:id="@+id/radio5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="RadioButton" /> </RadioGroup> </LinearLayout> </LinearLayout> 
-one
15 . '15 13:57
source share



All Articles