Skip to content

Instantly share code, notes, and snippets.

@ignaciotcrespo
Last active March 19, 2017 02:27
Show Gist options
  • Save ignaciotcrespo/365d3c476998884fd8aa321de5e2a47b to your computer and use it in GitHub Desktop.
Save ignaciotcrespo/365d3c476998884fd8aa321de5e2a47b to your computer and use it in GitHub Desktop.
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import java.util.ArrayList;
import java.util.List;
/**
* {@link RadioGroup} supporting mutual exclusion in all {@link RadioButton} in the layout tree.
* For my friend Gryzor ;)
*/
class DeepRadioGroup extends RadioGroup {
private List<RadioButton> radioButtons = new ArrayList<>();
private OnCheckedChangeListener onCheckedChangeListener;
private OnHierarchyChangeListener onHierarchyChangeListener;
private CompoundButton.OnCheckedChangeListener radioButtonChangeListener;
public DeepRadioGroup(Context context) {
super(context);
init();
}
public DeepRadioGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
super.setOnHierarchyChangeListener(new HierarchyChangeListener(this));
radioButtonChangeListener = new RadioButtonChangeListener(this);
}
private void addRadioButton(RadioButton button) {
radioButtons.add(button);
button.setOnCheckedChangeListener(radioButtonChangeListener);
}
private void removeRadioButton(RadioButton child) {
radioButtons.remove(child);
}
@Override
public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
onHierarchyChangeListener = listener;
}
private void delegateOnChildViewAdded(View parent, View child) {
if (onHierarchyChangeListener != null) {
onHierarchyChangeListener.onChildViewAdded(parent, child);
}
}
private void delegateOnChildViewRemoved(View parent, View child) {
if (onHierarchyChangeListener != null) {
onHierarchyChangeListener.onChildViewRemoved(parent, child);
}
}
@Override
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
super.setOnCheckedChangeListener(listener);
this.onCheckedChangeListener = listener;
}
private void triggerMutualExclusion(CompoundButton checked) {
super.setOnCheckedChangeListener(null);
for (RadioButton button : radioButtons) {
if (button != checked) {
button.setChecked(false);
}
}
super.setOnCheckedChangeListener(onCheckedChangeListener);
}
private static class RadioButtonChangeListener implements CompoundButton.OnCheckedChangeListener {
private DeepRadioGroup group;
private RadioButtonChangeListener(DeepRadioGroup group) {
this.group = group;
}
@Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {
if (isChecked) {
group.triggerMutualExclusion(button);
}
}
}
@SuppressWarnings("StatementWithEmptyBody")
private static class HierarchyChangeListener implements OnHierarchyChangeListener {
private DeepRadioGroup group;
private HierarchyChangeListener(DeepRadioGroup group) {
this.group = group;
}
@Override
public void onChildViewAdded(View parent, View child) {
if (child instanceof RadioGroup) {
// ignore nested groups
} else if (child instanceof RadioButton) {
group.addRadioButton((RadioButton) child);
} else if (child instanceof ViewGroup) {
ViewGroup group = (ViewGroup) child;
for (int i = 0; i < group.getChildCount(); i++) {
onChildViewAdded(child, group.getChildAt(i));
}
}
group.delegateOnChildViewAdded(parent, child);
}
@Override
public void onChildViewRemoved(View parent, View child) {
if (child instanceof RadioGroup) {
// ignore nested groups
} else if (child instanceof RadioButton) {
group.removeRadioButton((RadioButton) child);
} else if (child instanceof ViewGroup) {
ViewGroup group = (ViewGroup) child;
for (int i = 0; i < group.getChildCount(); i++) {
onChildViewRemoved(child, group.getChildAt(i));
}
}
group.delegateOnChildViewRemoved(parent, child);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment