diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
| commit | 54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch) | |
| tree | 35051494d2af230dce54d6b31c6af8fc24091316 /core/java/android/widget/CompoundButton.java | |
Initial Contribution
Diffstat (limited to 'core/java/android/widget/CompoundButton.java')
| -rw-r--r-- | core/java/android/widget/CompoundButton.java | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java new file mode 100644 index 000000000000..e56a7411aaeb --- /dev/null +++ b/core/java/android/widget/CompoundButton.java @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.widget; + +import com.android.internal.R; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.view.Gravity; + + +/** + * <p> + * A button with two states, checked and unchecked. When the button is pressed + * or clicked, the state changes automatically. + * </p> + * + * <p><strong>XML attributes</strong></p> + * <p> + * See {@link android.R.styleable#CompoundButton + * CompoundButton Attributes}, {@link android.R.styleable#Button Button + * Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link + * android.R.styleable#View View Attributes} + * </p> + */ +public abstract class CompoundButton extends Button implements Checkable { + private boolean mChecked; + private int mButtonResource; + private boolean mBroadcasting; + private Drawable mButtonDrawable; + private OnCheckedChangeListener mOnCheckedChangeListener; + private OnCheckedChangeListener mOnCheckedChangeWidgetListener; + + private static final int[] CHECKED_STATE_SET = { + R.attr.state_checked + }; + + public CompoundButton(Context context) { + this(context, null); + } + + public CompoundButton(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CompoundButton(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = + context.obtainStyledAttributes( + attrs, com.android.internal.R.styleable.CompoundButton, defStyle, 0); + + Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button); + if (d != null) { + setButtonDrawable(d); + } + + boolean checked = a + .getBoolean(com.android.internal.R.styleable.CompoundButton_checked, false); + setChecked(checked); + + a.recycle(); + } + + public void toggle() { + setChecked(!mChecked); + } + + @Override + public boolean performClick() { + /* + * XXX: These are tiny, need some surrounding 'expanded touch area', + * which will need to be implemented in Button if we only override + * performClick() + */ + + /* When clicked, toggle the state */ + toggle(); + return super.performClick(); + } + + public boolean isChecked() { + return mChecked; + } + + /** + * <p>Changes the checked state of this button.</p> + * + * @param checked true to check the button, false to uncheck it + */ + public void setChecked(boolean checked) { + if (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); + } + if (mOnCheckedChangeWidgetListener != null) { + mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); + } + mBroadcasting = false; + } + } + + /** + * 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; + } + + /** + * Register a callback to be invoked when the checked state of this button + * changes. This callback is used for internal purpose only. + * + * @param listener the callback to call on checked state change + * @hide + */ + void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) { + mOnCheckedChangeWidgetListener = listener; + } + + /** + * Interface definition for a callback to be invoked when the checked state + * of a compound button changed. + */ + public static interface OnCheckedChangeListener { + /** + * Called when the checked state of a compound button has changed. + * + * @param buttonView The compound button view whose state has changed. + * @param isChecked The new checked state of buttonView. + */ + void onCheckedChanged(CompoundButton buttonView, boolean isChecked); + } + + /** + * Set the background to a given Drawable, identified by its resource id. + * + * @param resid the resource id of the drawable to use as the background + */ + public void setButtonDrawable(int resid) { + if (resid != 0 && resid == mButtonResource) { + return; + } + + mButtonResource = resid; + + Drawable d = null; + if (mButtonResource != 0) { + d = getResources().getDrawable(mButtonResource); + } + setButtonDrawable(d); + } + + /** + * Set the background to a given Drawable + * + * @param d The Drawable to use as the background + */ + public void setButtonDrawable(Drawable d) { + if (d != null) { + if (mButtonDrawable != null) { + mButtonDrawable.setCallback(null); + unscheduleDrawable(mButtonDrawable); + } + d.setCallback(this); + d.setState(getDrawableState()); + d.setVisible(getVisibility() == VISIBLE, false); + mButtonDrawable = d; + mButtonDrawable.setState(null); + setMinHeight(mButtonDrawable.getIntrinsicHeight()); + } + + refreshDrawableState(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + final Drawable buttonDrawable = mButtonDrawable; + if (buttonDrawable != null) { + final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; + final int height = buttonDrawable.getIntrinsicHeight(); + + int y = 0; + + switch (verticalGravity) { + case Gravity.BOTTOM: + y = getHeight() - height; + break; + case Gravity.CENTER_VERTICAL: + y = (getHeight() - height) / 2; + break; + } + + buttonDrawable.setBounds(0, y, buttonDrawable.getIntrinsicWidth(), y + height); + buttonDrawable.draw(canvas); + } + } + + @Override + protected 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(); + + if (mButtonDrawable != null) { + int[] myDrawableState = getDrawableState(); + + // Set the state of the Drawable + mButtonDrawable.setState(myDrawableState); + + invalidate(); + } + } + + static class SavedState extends BaseSavedState { + boolean checked; + + /** + * Constructor called from {@link CompoundButton#onSaveInstanceState()} + */ + SavedState(Parcelable superState) { + super(superState); + } + + /** + * Constructor called from {@link #CREATOR} + */ + 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); + } + + @Override + public String toString() { + return "CompoundButton.SavedState{" + + Integer.toHexString(System.identityHashCode(this)) + + " checked=" + checked + "}"; + } + + 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]; + } + }; + } + + @Override + public Parcelable onSaveInstanceState() { + // Force our ancestor class to save its state + setFreezesText(true); + 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(); + } +} |
