CompoundButton.java revision f6d87ec193f17e8dad82c9994ba7a58e975d364b
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 196a394f4def305560c9b7ca3a14b3a313556db36eAlan Viveretteimport android.annotation.DrawableRes; 2094a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamyimport android.annotation.NonNull; 21911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viveretteimport android.annotation.Nullable; 22911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viveretteimport android.graphics.PorterDuff; 2394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamyimport android.view.ViewHierarchyEncoder; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.R; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 27911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viveretteimport android.content.res.ColorStateList; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 35d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viveretteimport android.view.SoundEffectConstants; 367a36788f4a69b3ddaf8fb8e250e1a13bee7238faSteve Zeiglerimport android.view.ViewDebug; 37cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queruimport android.view.accessibility.AccessibilityEvent; 3813774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A button with two states, checked and unchecked. When the button is pressed 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or clicked, the state changes automatically. 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><strong>XML attributes</strong></p> 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See {@link android.R.styleable#CompoundButton 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CompoundButton Attributes}, {@link android.R.styleable#Button Button 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android.R.styleable#View View Attributes} 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class CompoundButton extends Button implements Checkable { 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mChecked; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mBroadcasting; 57911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mButtonDrawable; 59a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette private ColorStateList mButtonTintList = null; 60b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette private PorterDuff.Mode mButtonTintMode = null; 61911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette private boolean mHasButtonTint = false; 62b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette private boolean mHasButtonTintMode = false; 63911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnCheckedChangeListener mOnCheckedChangeListener; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnCheckedChangeListener mOnCheckedChangeWidgetListener; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] CHECKED_STATE_SET = { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project R.attr.state_checked 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CompoundButton(Context context) { 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, null); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CompoundButton(Context context, AttributeSet attrs) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, attrs, 0); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public CompoundButton(Context context, AttributeSet attrs, int defStyleAttr) { 80617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 81617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 82617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 83617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public CompoundButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 84617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 86617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette final TypedArray a = context.obtainStyledAttributes( 87617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette attrs, com.android.internal.R.styleable.CompoundButton, defStyleAttr, defStyleRes); 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 89911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette final Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (d != null) { 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setButtonDrawable(d); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 94b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (a.hasValue(R.styleable.CompoundButton_buttonTintMode)) { 95b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mButtonTintMode = Drawable.parseTintMode(a.getInt( 96b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette R.styleable.CompoundButton_buttonTintMode, -1), mButtonTintMode); 97b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mHasButtonTintMode = true; 98b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 994f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette 100911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette if (a.hasValue(R.styleable.CompoundButton_buttonTint)) { 101a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mButtonTintList = a.getColorStateList(R.styleable.CompoundButton_buttonTint); 102911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mHasButtonTint = true; 103911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 104911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 105911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette final boolean checked = a.getBoolean( 106911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette com.android.internal.R.styleable.CompoundButton_checked, false); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChecked(checked); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 110b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 111b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette applyButtonTint(); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void toggle() { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChecked(!mChecked); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performClick() { 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toggle(); 121d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette 122d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette final boolean handled = super.performClick(); 123d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette if (!handled) { 124d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette // View only makes a sound effect if the onClickListener was 125d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette // called, so we'll need to make one here instead. 126d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette playSoundEffect(SoundEffectConstants.CLICK); 127d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette } 128d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette 129d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette return handled; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1327a36788f4a69b3ddaf8fb8e250e1a13bee7238faSteve Zeigler @ViewDebug.ExportedProperty 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isChecked() { 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChecked; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Changes the checked state of this button.</p> 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param checked true to check the button, false to uncheck it 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChecked(boolean checked) { 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChecked != checked) { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChecked = checked; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project refreshDrawableState(); 14677e9a28e2faa36f127231b842476d47f9823a83aAlan Viverette notifyViewAccessibilityStateChangedIfNeeded( 14777e9a28e2faa36f127231b842476d47f9823a83aAlan Viverette AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Avoid infinite recursions if setChecked() is called from a listener 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBroadcasting) { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBroadcasting = true; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnCheckedChangeListener != null) { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCheckedChangeListener.onCheckedChanged(this, mChecked); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnCheckedChangeWidgetListener != null) { 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 161cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBroadcasting = false; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when the checked state of this button 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * changes. 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the callback to call on checked state change 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCheckedChangeListener = listener; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when the checked state of this button 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * changes. This callback is used for internal purpose only. 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the callback to call on checked state change 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCheckedChangeWidgetListener = listener; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Interface definition for a callback to be invoked when the checked state 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of a compound button changed. 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static interface OnCheckedChangeListener { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called when the checked state of a compound button has changed. 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param buttonView The compound button view whose state has changed. 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isChecked The new checked state of buttonView. 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onCheckedChanged(CompoundButton buttonView, boolean isChecked); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2026a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * Sets a drawable as the compound button image given its resource 2036a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * identifier. 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2056a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @param resId the resource identifier of the drawable 2066a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @attr ref android.R.styleable#CompoundButton_button 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2086a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette public void setButtonDrawable(@DrawableRes int resId) { 2096a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette final Drawable d; 2106a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette if (resId != 0) { 2116a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette d = getContext().getDrawable(resId); 2126a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette } else { 2136a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette d = null; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setButtonDrawable(d); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2196a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * Sets a drawable as the compound button image. 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2216a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @param drawable the drawable to set 2226a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @attr ref android.R.styleable#CompoundButton_button 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2246a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette @Nullable 2256a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette public void setButtonDrawable(@Nullable Drawable drawable) { 2266a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette if (mButtonDrawable != drawable) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mButtonDrawable != null) { 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mButtonDrawable.setCallback(null); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unscheduleDrawable(mButtonDrawable); 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 231911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 2326a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette mButtonDrawable = drawable; 233911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 2346a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette if (drawable != null) { 2356a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette drawable.setCallback(this); 2366a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette drawable.setLayoutDirection(getLayoutDirection()); 2376a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette if (drawable.isStateful()) { 2386a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette drawable.setState(getDrawableState()); 239911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 2406a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette drawable.setVisible(getVisibility() == VISIBLE, false); 2416a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette setMinHeight(drawable.getIntrinsicHeight()); 242911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette applyButtonTint(); 243911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 245911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 247911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 2483380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu * @hide 2493380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu */ 2503380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu @Override 2513380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { 2523380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu super.onResolveDrawables(layoutDirection); 2533380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu if (mButtonDrawable != null) { 2543380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu mButtonDrawable.setLayoutDirection(layoutDirection); 2553380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu } 2563380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu } 2573380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu 2583380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu /** 2596a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @return the drawable used as the compound button image 2606a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @see #setButtonDrawable(Drawable) 2616a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @see #setButtonDrawable(int) 2626a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette */ 2636a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette @Nullable 2646a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette public Drawable getButtonDrawable() { 2656a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette return mButtonDrawable; 2666a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette } 2676a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette 2686a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette /** 2694f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * Applies a tint to the button drawable. Does not modify the current tint 270b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 271911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * <p> 272911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * Subsequent calls to {@link #setButtonDrawable(Drawable)} will 273911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * automatically mutate the drawable and apply the specified tint and tint 274911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * mode using 275a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * {@link Drawable#setTintList(ColorStateList)}. 276911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 277911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @param tint the tint to apply, may be {@code null} to clear tint 278911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 279911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#CompoundButton_buttonTint 280a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see #setButtonTintList(ColorStateList) 281a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see Drawable#setTintList(ColorStateList) 282911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 283a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setButtonTintList(@Nullable ColorStateList tint) { 284a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mButtonTintList = tint; 285911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mHasButtonTint = true; 286911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 287911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette applyButtonTint(); 288911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 289911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 290911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 291911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @return the tint applied to the button drawable 292911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#CompoundButton_buttonTint 293a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see #setButtonTintList(ColorStateList) 294911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 295911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette @Nullable 296a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public ColorStateList getButtonTintList() { 297a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette return mButtonTintList; 298911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 299911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 300911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 301911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * Specifies the blending mode used to apply the tint specified by 302a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * {@link #setButtonTintList(ColorStateList)}} to the button drawable. The 303b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * default mode is {@link PorterDuff.Mode#SRC_IN}. 304911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 305911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @param tintMode the blending mode used to apply the tint, may be 306911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * {@code null} to clear tint 307911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#CompoundButton_buttonTintMode 3084f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @see #getButtonTintMode() 309a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see Drawable#setTintMode(PorterDuff.Mode) 310911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 311911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette public void setButtonTintMode(@Nullable PorterDuff.Mode tintMode) { 3124f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette mButtonTintMode = tintMode; 313b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mHasButtonTintMode = true; 3144f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette 3154f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette applyButtonTint(); 316911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 317911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 318911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 319911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @return the blending mode used to apply the tint to the button drawable 320911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#CompoundButton_buttonTintMode 3214f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @see #setButtonTintMode(PorterDuff.Mode) 322911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 323911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette @Nullable 324911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette public PorterDuff.Mode getButtonTintMode() { 325911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette return mButtonTintMode; 326911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 327911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 328911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette private void applyButtonTint() { 329b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mButtonDrawable != null && (mHasButtonTint || mHasButtonTintMode)) { 330911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mButtonDrawable = mButtonDrawable.mutate(); 331b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 332b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mHasButtonTint) { 333b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mButtonDrawable.setTintList(mButtonTintList); 334b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 335b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 336b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mHasButtonTintMode) { 337b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mButtonDrawable.setTintMode(mButtonTintMode); 338b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 339d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette 340d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette // The drawable (or one of its children) may not have been 341d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette // stateful before applying the tint, so let's try again. 342d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette if (mButtonDrawable.isStateful()) { 343d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette mButtonDrawable.setState(getDrawableState()); 344d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette } 345911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 348a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn @Override 349a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn public CharSequence getAccessibilityClassName() { 350a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn return CompoundButton.class.getName(); 351a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn } 352a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn 353a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 355a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 356a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onInitializeAccessibilityEventInternal(event); 357736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov event.setChecked(mChecked); 358cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru } 359cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru 360a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 361cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru @Override 362a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 363a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onInitializeAccessibilityNodeInfoInternal(info); 3640f55cc33f658b2793a12d609a0989348077324a4Svetoslav Ganov info.setCheckable(true); 36513774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganov info.setChecked(mChecked); 36613774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganov } 36713774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganov 36813774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganov @Override 3692842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio public int getCompoundPaddingLeft() { 3702842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio int padding = super.getCompoundPaddingLeft(); 3712842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio if (!isLayoutRtl()) { 3722842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio final Drawable buttonDrawable = mButtonDrawable; 3732842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio if (buttonDrawable != null) { 3742842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio padding += buttonDrawable.getIntrinsicWidth(); 3752842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3762842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3772842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio return padding; 3782842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3792842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio 3802842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio @Override 3812842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio public int getCompoundPaddingRight() { 3822842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio int padding = super.getCompoundPaddingRight(); 3832842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio if (isLayoutRtl()) { 3842842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio final Drawable buttonDrawable = mButtonDrawable; 3852842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio if (buttonDrawable != null) { 3862842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio padding += buttonDrawable.getIntrinsicWidth(); 3872842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3882842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3892842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio return padding; 3902842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3912842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio 392b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio /** 393b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio * @hide 394b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio */ 395b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio @Override 396b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio public int getHorizontalOffsetForDrawables() { 397b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio final Drawable buttonDrawable = mButtonDrawable; 398b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio return (buttonDrawable != null) ? buttonDrawable.getIntrinsicWidth() : 0; 399b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio } 400b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio 4012842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio @Override 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onDraw(Canvas canvas) { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Drawable buttonDrawable = mButtonDrawable; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buttonDrawable != null) { 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; 4062842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio final int drawableHeight = buttonDrawable.getIntrinsicHeight(); 4072842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio final int drawableWidth = buttonDrawable.getIntrinsicWidth(); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 40961956606818918194a38e045a8e35e7108480e5eAlan Viverette final int top; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (verticalGravity) { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case Gravity.BOTTOM: 4122842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio top = getHeight() - drawableHeight; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case Gravity.CENTER_VERTICAL: 4152842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio top = (getHeight() - drawableHeight) / 2; 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 41761956606818918194a38e045a8e35e7108480e5eAlan Viverette default: 41861956606818918194a38e045a8e35e7108480e5eAlan Viverette top = 0; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 42061956606818918194a38e045a8e35e7108480e5eAlan Viverette final int bottom = top + drawableHeight; 42161956606818918194a38e045a8e35e7108480e5eAlan Viverette final int left = isLayoutRtl() ? getWidth() - drawableWidth : 0; 42261956606818918194a38e045a8e35e7108480e5eAlan Viverette final int right = isLayoutRtl() ? getWidth() : drawableWidth; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4242842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio buttonDrawable.setBounds(left, top, right, bottom); 42561956606818918194a38e045a8e35e7108480e5eAlan Viverette 42661956606818918194a38e045a8e35e7108480e5eAlan Viverette final Drawable background = getBackground(); 427c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette if (background != null) { 42861956606818918194a38e045a8e35e7108480e5eAlan Viverette background.setHotspotBounds(left, top, right, bottom); 42961956606818918194a38e045a8e35e7108480e5eAlan Viverette } 43061956606818918194a38e045a8e35e7108480e5eAlan Viverette } 43161956606818918194a38e045a8e35e7108480e5eAlan Viverette 43261956606818918194a38e045a8e35e7108480e5eAlan Viverette super.onDraw(canvas); 43361956606818918194a38e045a8e35e7108480e5eAlan Viverette 43461956606818918194a38e045a8e35e7108480e5eAlan Viverette if (buttonDrawable != null) { 435b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette final int scrollX = mScrollX; 436b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette final int scrollY = mScrollY; 437b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette if (scrollX == 0 && scrollY == 0) { 438b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette buttonDrawable.draw(canvas); 439b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette } else { 440b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette canvas.translate(scrollX, scrollY); 441b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette buttonDrawable.draw(canvas); 442b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette canvas.translate(-scrollX, -scrollY); 443b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int[] onCreateDrawableState(int extraSpace) { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isChecked()) { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mergeDrawableStates(drawableState, CHECKED_STATE_SET); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return drawableState; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void drawableStateChanged() { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.drawableStateChanged(); 459ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette 460ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette final Drawable buttonDrawable = mButtonDrawable; 461ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette if (buttonDrawable != null && buttonDrawable.isStateful() 462ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette && buttonDrawable.setState(getDrawableState())) { 463ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette invalidateDrawable(buttonDrawable); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 467cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette @Override 4688de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette public void drawableHotspotChanged(float x, float y) { 4698de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette super.drawableHotspotChanged(x, y); 470cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette 471cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette if (mButtonDrawable != null) { 472cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette mButtonDrawable.setHotspot(x, y); 473cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette } 474cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette } 475cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 477f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette protected boolean verifyDrawable(@NonNull Drawable who) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.verifyDrawable(who) || who == mButtonDrawable; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 481e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn @Override 482e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn public void jumpDrawablesToCurrentState() { 483e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn super.jumpDrawablesToCurrentState(); 484e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); 485e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn } 486e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class SavedState extends BaseSavedState { 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean checked; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link CompoundButton#onSaveInstanceState()} 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState(Parcelable superState) { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(superState); 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link #CREATOR} 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SavedState(Parcel in) { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(in); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checked = (Boolean)in.readValue(null); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void writeToParcel(Parcel out, int flags) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.writeToParcel(out, flags); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeValue(checked); 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "CompoundButton.SavedState{" 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Integer.toHexString(System.identityHashCode(this)) 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " checked=" + checked + "}"; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Parcelable.Creator<SavedState> CREATOR 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new Parcelable.Creator<SavedState>() { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState createFromParcel(Parcel in) { 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(in); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState[] newArray(int size) { 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState[size]; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Parcelable onSaveInstanceState() { 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcelable superState = super.onSaveInstanceState(); 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState ss = new SavedState(superState); 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ss.checked = isChecked(); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ss; 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onRestoreInstanceState(Parcelable state) { 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState ss = (SavedState) state; 54394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onRestoreInstanceState(ss.getSuperState()); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChecked(ss.checked); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 54894a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy 54994a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy /** @hide */ 55094a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy @Override 55194a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { 55294a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy super.encodeProperties(stream); 55394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy stream.addProperty("checked", isChecked()); 55494a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 556