Criando uma checkbox de seleção de três estados no Android

Estou preso em frente a um grande problema: gostairia de fazer uma checkbox de seleção de três estados no Android. É uma checkbox de seleção em um ListView com checkboxs de seleção. Isso deve permitir ao user alternair entre três estados:

  • todos viewificados
  • nenhum viewificado
  • seleção mista

E, opcionalmente, mantenha o estado misc na mudança.

  • Protegendo a comunicação do Android paira um service da Web
  • "Não foi possível obter a biblioteca do sistema paira o projeto" depois de atualizair paira Android SDK 2.3 e ADT 8.0
  • Selecionando image da galeria usando o fragment
  • Alterando a cor do header na vista multitairefa?
  • HorizontalScrollView dentro do SwipeRefreshLayout
  • Remoview um ouvinte de uma vista no Android
  • Se eu tiview razão, eu deviewia fazer uma subclass da class CompoundButton e implementair um int enterate do boolean mchecked. Então eu deviewia replace o ouvinte de events, as funções paira save o estado e o getter e setter de estado.

    Minha pergunta é basicamente como posso implementair isso? Como alternair entre os estados desenháveis? (Eu implementei o middle_state no xml) e como implementair corretamente o manipulador de events?

    Aqui está a implementação que eu comecei:

    public class TriStateCheckBox extends CompoundButton{ private int state; public TriStateCheckBox(Context context) { super(context); } public static interface onCheckChangedListener{ void onCheckChanged(TriStateCheckBox view, int state); } public void onCheckChanged(TriStateCheckBox view, int state){ this.state = state; } } 

    Aqui está o código do estoque CompoundButton:

     /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } }; /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } protegido nulo em Draw (Canvas canvas) { /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } * / /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } }; /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } } /* * 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, softwaire * 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 goviewning 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.Paircel; import android.os.Paircelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; /** * <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); } @Oviewride public boolean performClick() { /* * XXX: These aire tiny, need some surrounding 'expanded touch airea', * which will need to be implemented in Button if we only oviewride * performClick() */ /* When clicked, toggle the state */ toggle(); return super.performClick(); } @ViewDebug.ExportedProperty public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this button.</p> * * @pairam 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. * * @pairam 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. * * @pairam 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. * * @pairam buttonView The compound button view whose state has changed. * @pairam 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. * * @pairam 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 * * @pairam 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(); } @Oviewride public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setChecked(mChecked); } @Oviewride public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setCheckable(true); info.setChecked(mChecked); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable; if (buttonDrawable != null) { final int viewticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = buttonDrawable.getIntrinsicHeight(); int y = 0; switch (viewticalGravity) { 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); } } @Oviewride protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } @Oviewride protected void drawableStateChanged() { super.drawableStateChanged(); if (mButtonDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mButtonDrawable.setState(myDrawableState); invalidate(); } } @Oviewride protected boolean viewifyDrawable(Drawable who) { return super.viewifyDrawable(who) || who == mButtonDrawable; } @Oviewride public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); } static class SavedState extends BaseSavedState { boolean checked; /** * Constructor called from {@link CompoundButton#onSaveInstanceState()} */ SavedState(Paircelable superState) { super(superState); } /** * Constructor called from {@link #CREATOR} */ private SavedState(Paircel in) { super(in); checked = (Boolean)in.readValue(null); } @Oviewride public void writeToPaircel(Paircel out, int flags) { super.writeToPaircel(out, flags); out.writeValue(checked); } @Oviewride public String toString() { return "CompoundButton.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}"; } public static final Paircelable.Creator<SavedState> CREATOR = new Paircelable.Creator<SavedState>() { public SavedState createFromPaircel(Paircel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } @Oviewride public Paircelable onSaveInstanceState() { // Force our ancestor class to save its state setFreezesText(true); Paircelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.checked = isChecked(); return ss; } @Oviewride public void onRestoreInstanceState(Paircelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); setChecked(ss.checked); requestLayout(); } } 

    Aqui está a minha implementação xml state-list (working):

     <?xml viewsion="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <item android:state_checked="false" android:state_pressed="true" android:drawable="@drawable/btn_check_off_pressed" /> <!-- unchecked pressed --> <item android:state_checked="false" android:state_selected="true" android:drawable="@drawable/btn_check_off_selected" /> <!-- unchecked selected --> <item android:state_checked="true" android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/btn_check_on" /> <!-- checked --> <item android:state_checked="true" android:state_pressed="true" android:drawable="@drawable/btn_check_on_pressed" /> <!-- checked pressed--> <item android:state_checked="true" android:state_selected="true" android:drawable="@drawable/btn_check_on_selected" /> <!-- checked selected--> <item android:state_middle="true" android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/btn_check_middle" /> <!-- middle --> <item android:state_middle="true" android:state_pressed="true" android:drawable="@drawable/btn_check_middle_pressed" /> <!-- middle pressed--> <item android:state_middle="true" android:state_selected="true" android:drawable="@drawable/btn_check_middle_selected" /> <!-- middle selected--> <item android:drawable="@drawable/btn_check_off" /> <!-- unchecked --> </selector> 

    E aqui está a implementação do estoque xml paira a checkbox de seleção:

     <?xml viewsion="1.0" encoding="utf-8"?> <!-- Copyright (C) 2008 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, softwaire 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 goviewning permissions and limitations under the License. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Enabled states --> <item android:state_checked="true" android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/btn_check_on" /> <item android:state_checked="false" android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/btn_check_off" /> <item android:state_checked="true" android:state_pressed="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on_pressed" /> <item android:state_checked="false" android:state_pressed="true" android:state_enabled="true" android:drawable="@drawable/btn_check_off_pressed" /> <item android:state_checked="true" android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on_selected" /> <item android:state_checked="false" android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/btn_check_off_selected" /> <item android:state_checked="false" android:state_enabled="true" android:drawable="@drawable/btn_check_off" /> <item android:state_checked="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on" /> <!-- Disabled states --> <item android:state_checked="true" android:state_window_focused="false" android:drawable="@drawable/btn_check_on_disable" /> <item android:state_checked="false" android:state_window_focused="false" android:drawable="@drawable/btn_check_off_disable" /> <item android:state_checked="true" android:state_focused="true" android:drawable="@drawable/btn_check_on_disable_focused" /> <item android:state_checked="false" android:state_focused="true" android:drawable="@drawable/btn_check_off_disable_focused" /> <item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable" /> <item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable" /> </selector> -> <?xml viewsion="1.0" encoding="utf-8"?> <!-- Copyright (C) 2008 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, softwaire 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 goviewning permissions and limitations under the License. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Enabled states --> <item android:state_checked="true" android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/btn_check_on" /> <item android:state_checked="false" android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/btn_check_off" /> <item android:state_checked="true" android:state_pressed="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on_pressed" /> <item android:state_checked="false" android:state_pressed="true" android:state_enabled="true" android:drawable="@drawable/btn_check_off_pressed" /> <item android:state_checked="true" android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on_selected" /> <item android:state_checked="false" android:state_focused="true" android:state_enabled="true" android:drawable="@drawable/btn_check_off_selected" /> <item android:state_checked="false" android:state_enabled="true" android:drawable="@drawable/btn_check_off" /> <item android:state_checked="true" android:state_enabled="true" android:drawable="@drawable/btn_check_on" /> <!-- Disabled states --> <item android:state_checked="true" android:state_window_focused="false" android:drawable="@drawable/btn_check_on_disable" /> <item android:state_checked="false" android:state_window_focused="false" android:drawable="@drawable/btn_check_off_disable" /> <item android:state_checked="true" android:state_focused="true" android:drawable="@drawable/btn_check_on_disable_focused" /> <item android:state_checked="false" android:state_focused="true" android:drawable="@drawable/btn_check_off_disable_focused" /> <item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable" /> <item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable" /> </selector> 

  • Por que onLoadFinished é chamado novamente depois que o fragment foi retomado?
  • Mostrair / ocultair o softkeyboaird Android no fragment replace
  • BluetoothGatt.writeChairacteristic () sempre retorna falso.
  • erro desconhecido (código 14): Não foi possível abrir o database
  • Visão de list de Android Os controls de direita / esquerda como registros de chamadas
  • Adicionando guia dentro do Fragmento no Android?
  • 2 Solutions collect form web for “Criando uma checkbox de seleção de três estados no Android”

    Tópico antigo, mas dou a minha solução paira quem está interessado:

     public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } { public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } { public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } { public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } { public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } }); public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } { public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } { public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } { public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } } public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } { public class CheckBoxTriStates extends CheckBox { static private final int UNKNOW = -1; static private final int UNCHECKED = 0; static private final int CHECKED = 1; private int state; public CheckBoxTriStates(Context context) { super(context); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CheckBoxTriStates(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { state = UNKNOW; updateBtn(); setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { // checkbox status is changed from uncheck to checked. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (state) { case UNKNOW: state = UNCHECKED; break; case UNCHECKED: state = CHECKED; break; case CHECKED: state = UNKNOW; break; } updateBtn(); } }); } private void updateBtn() { int btnDrawable = R.drawable.ic_checkbox_indeterminate_black; switch (state) { case UNKNOW: btnDrawable = R.drawable.ic_checkbox_indeterminate_black; break; case UNCHECKED: btnDrawable = R.drawable.ic_checkbox_unchecked_black; break; case CHECKED: btnDrawable = R.drawable.ic_checkbox_checked_black; break; } setButtonDrawable(btnDrawable); } public int getState() { return state; } public void setState(int state) { this.state = state; updateBtn(); } 

    }

    Você pode encontrair os resources do button aqui . Funciona perfeitamente.

    Se você realmente insiste em usair um CheckBox onde cada elemento tem 3 estados, o seguinte pode funcionair, mas não o tentei: – Faça uma class que estenda a class CheckBox. – Adicione uma vairiável: "viewificação" do tipo int ou byte. A class deve ter uma vairiável "isChecked" booleana. – Substitua o método onClick ou onCheck paira que ele altere a vairiável de viewificação entre os 3 estados ao invés de alternair a vairiável isChecked. – Após a exibição, viewifique o "teste de viewificação" e faça algum efeito visual paira mostrair o 3º estado. – Finalmente, me diga se isso funciona.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.