package com.circlegate.liban.view; import android.content.Context; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.CheckBox; import android.widget.Checkable; import android.widget.ImageButton; public class CheckableImageButton extends ImageButton implements Checkable { private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked }; private boolean mChecked; private boolean mBroadcasting; private OnCheckedChangeListener mOnCheckedChangeListener; public CheckableImageButton(Context context) { this(context, null); } public CheckableImageButton(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CheckableImageButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } // // GETTERS // @Override public boolean isChecked() { return mChecked; } // // SETTERS // @Override public void setChecked(boolean checked) { if (this.mChecked != checked) { mChecked = checked; refreshDrawableState(); // Avoid infinite recursions if setChecked() is called from a listener if (mBroadcasting) { return; } mBroadcasting = true; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(this, mChecked); } mBroadcasting = false; } } @Override public void toggle() { setChecked(!mChecked); } @Override public boolean performClick() { toggle(); return super.performClick(); } // // CALLBACKS // /** * Register a callback to be invoked when the checked state of this button changes. * * @param listener * the callback to call on checked state change */ public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { mOnCheckedChangeListener = listener; } /** * Interface definition for a callback. */ public static interface OnCheckedChangeListener { /** * Called when the checked state of a button has changed. * * @param button * The button view whose state has changed. * @param isChecked * The new checked state of button. */ void onCheckedChanged(CheckableImageButton button, boolean isChecked); } @Override public int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Override protected void drawableStateChanged() { super.drawableStateChanged(); invalidate(); } @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(isChecked()); event.setClassName(CheckBox.class.getName()); } @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); if (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) { info.setCheckable(true); info.setChecked(isChecked()); info.setClassName(CheckBox.class.getName()); } } // // SAVED STATE // public static class SavedState extends BaseSavedState { boolean checked; public SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); checked = (Boolean) in.readValue(null); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeValue(checked); } public static final Creator<SavedState> CREATOR = new Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Override public void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } }