Created
June 4, 2015 01:04
-
-
Save gfpacheco/00aa262c4e972e81c6a5 to your computer and use it in GitHub Desktop.
A GridLayout subclass that serves as RadioButton group and has same methods than original RadioGroup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.gfpacheco.views.widget; | |
import android.content.Context; | |
import android.support.annotation.NonNull; | |
import android.support.v7.widget.AppCompatRadioButton; | |
import android.support.v7.widget.GridLayout; | |
import android.util.AttributeSet; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.view.accessibility.AccessibilityEvent; | |
import android.view.accessibility.AccessibilityNodeInfo; | |
import android.widget.CompoundButton; | |
import com.gfpacheco.utils.ViewUtils; | |
public class RadioGridGroup extends GridLayout { | |
private int mCheckedId = -1; | |
private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener; | |
private boolean mProtectFromCheckedChange = false; | |
private OnCheckedChangeListener mOnCheckedChangeListener; | |
private PassThroughHierarchyChangeListener mPassThroughListener; | |
public RadioGridGroup(Context context) { | |
super(context); | |
init(); | |
} | |
public RadioGridGroup(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
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(@NonNull View child, int index, ViewGroup.LayoutParams params) { | |
if (child instanceof AppCompatRadioButton) { | |
final AppCompatRadioButton button = (AppCompatRadioButton) 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(int id) { | |
if (id != -1 && (id == mCheckedId)) { | |
return; | |
} | |
if (mCheckedId != -1) { | |
setCheckedStateForView(mCheckedId, false); | |
} | |
if (id != -1) { | |
setCheckedStateForView(id, true); | |
} | |
setCheckedId(id); | |
} | |
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 (checkedView != null && checkedView instanceof AppCompatRadioButton) { | |
((AppCompatRadioButton) checkedView).setChecked(checked); | |
} | |
} | |
public int getCheckedAppCompatRadioButtonId() { | |
return mCheckedId; | |
} | |
public void clearCheck() { | |
check(-1); | |
} | |
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { | |
mOnCheckedChangeListener = listener; | |
} | |
@Override | |
public void onInitializeAccessibilityEvent(@NonNull AccessibilityEvent event) { | |
super.onInitializeAccessibilityEvent(event); | |
event.setClassName(RadioGridGroup.class.getName()); | |
} | |
@Override | |
public void onInitializeAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info) { | |
super.onInitializeAccessibilityNodeInfo(info); | |
info.setClassName(RadioGridGroup.class.getName()); | |
} | |
public interface OnCheckedChangeListener { | |
void onCheckedChanged(RadioGridGroup group, int checkedId); | |
} | |
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener { | |
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; | |
public void onChildViewAdded(View parent, View child) { | |
if (parent == RadioGridGroup.this && child instanceof AppCompatRadioButton) { | |
int id = child.getId(); | |
// generates an id if it's missing | |
if (id == View.NO_ID) { | |
id = ViewUtils.generateViewId(); | |
child.setId(id); | |
} | |
((AppCompatRadioButton) child).setOnCheckedChangeListener( | |
mChildOnCheckedChangeListener); | |
} | |
if (mOnHierarchyChangeListener != null) { | |
mOnHierarchyChangeListener.onChildViewAdded(parent, child); | |
} | |
} | |
public void onChildViewRemoved(View parent, View child) { | |
if (parent == RadioGridGroup.this && child instanceof AppCompatRadioButton) { | |
((AppCompatRadioButton) child).setOnCheckedChangeListener(null); | |
} | |
if (mOnHierarchyChangeListener != null) { | |
mOnHierarchyChangeListener.onChildViewRemoved(parent, child); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment