CompoundButton.java revision c9a19b1b274af1fdd8b811c9ce2df994f7db47a4
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; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 23911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viveretteimport android.content.res.ColorStateList; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 2699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport android.graphics.PorterDuff; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 32d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viveretteimport android.view.SoundEffectConstants; 337a36788f4a69b3ddaf8fb8e250e1a13bee7238faSteve Zeiglerimport android.view.ViewDebug; 3499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport android.view.ViewHierarchyEncoder; 35c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Lemeimport android.view.ViewStructure; 36cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queruimport android.view.accessibility.AccessibilityEvent; 3713774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 38640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemeimport android.view.autofill.AutofillManager; 39640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemeimport android.view.autofill.AutofillValue; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4199441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport com.android.internal.R; 4299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A button with two states, checked and unchecked. When the button is pressed 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or clicked, the state changes automatically. 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><strong>XML attributes</strong></p> 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See {@link android.R.styleable#CompoundButton 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CompoundButton Attributes}, {@link android.R.styleable#Button Button 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android.R.styleable#View View Attributes} 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class CompoundButton extends Button implements Checkable { 586d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mChecked; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mBroadcasting; 61911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mButtonDrawable; 63a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette private ColorStateList mButtonTintList = null; 64b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette private PorterDuff.Mode mButtonTintMode = null; 65911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette private boolean mHasButtonTint = false; 66b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette private boolean mHasButtonTintMode = false; 67911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnCheckedChangeListener mOnCheckedChangeListener; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnCheckedChangeListener mOnCheckedChangeWidgetListener; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 71c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme // Indicates whether the toggle state was set from resources or dynamically, so it can be used 72640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme // to sanitize autofill requests. 73c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme private boolean mCheckedFromResource = false; 74c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] CHECKED_STATE_SET = { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project R.attr.state_checked 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CompoundButton(Context context) { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, null); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CompoundButton(Context context, AttributeSet attrs) { 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, attrs, 0); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 87617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public CompoundButton(Context context, AttributeSet attrs, int defStyleAttr) { 88617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 89617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 90617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 91617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public CompoundButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 92617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 94617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette final TypedArray a = context.obtainStyledAttributes( 95617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette attrs, com.android.internal.R.styleable.CompoundButton, defStyleAttr, defStyleRes); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 97911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette final Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (d != null) { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setButtonDrawable(d); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 102b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (a.hasValue(R.styleable.CompoundButton_buttonTintMode)) { 103b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mButtonTintMode = Drawable.parseTintMode(a.getInt( 104b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette R.styleable.CompoundButton_buttonTintMode, -1), mButtonTintMode); 105b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mHasButtonTintMode = true; 106b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 1074f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette 108911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette if (a.hasValue(R.styleable.CompoundButton_buttonTint)) { 109a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mButtonTintList = a.getColorStateList(R.styleable.CompoundButton_buttonTint); 110911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mHasButtonTint = true; 111911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 112911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 113911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette final boolean checked = a.getBoolean( 114911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette com.android.internal.R.styleable.CompoundButton_checked, false); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChecked(checked); 116c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme mCheckedFromResource = true; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 119b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 120b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette applyButtonTint(); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1236d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void toggle() { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChecked(!mChecked); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performClick() { 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project toggle(); 131d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette 132d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette final boolean handled = super.performClick(); 133d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette if (!handled) { 134d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette // View only makes a sound effect if the onClickListener was 135d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette // called, so we'll need to make one here instead. 136d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette playSoundEffect(SoundEffectConstants.CLICK); 137d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette } 138d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette 139d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette return handled; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1427a36788f4a69b3ddaf8fb8e250e1a13bee7238faSteve Zeigler @ViewDebug.ExportedProperty 1436d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isChecked() { 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChecked; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Changes the checked state of this button.</p> 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param checked true to check the button, false to uncheck it 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1536d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChecked(boolean checked) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChecked != checked) { 156c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme mCheckedFromResource = false; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChecked = checked; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project refreshDrawableState(); 15977e9a28e2faa36f127231b842476d47f9823a83aAlan Viverette notifyViewAccessibilityStateChangedIfNeeded( 16077e9a28e2faa36f127231b842476d47f9823a83aAlan Viverette AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Avoid infinite recursions if setChecked() is called from a listener 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mBroadcasting) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBroadcasting = true; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnCheckedChangeListener != null) { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCheckedChangeListener.onCheckedChanged(this, mChecked); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnCheckedChangeWidgetListener != null) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 174640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme final AutofillManager afm = mContext.getSystemService(AutofillManager.class); 1755882c4f5d2ff552a233ba88d2445f6810dd7599bFelipe Leme if (afm != null) { 1765882c4f5d2ff552a233ba88d2445f6810dd7599bFelipe Leme afm.valueChanged(this); 1775882c4f5d2ff552a233ba88d2445f6810dd7599bFelipe Leme } 178cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru 17999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mBroadcasting = false; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when the checked state of this button 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * changes. 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the callback to call on checked state change 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 189acdaaea50c543276c70aaa32d6b33aa61a9f6195Jason Long public void setOnCheckedChangeListener(@Nullable OnCheckedChangeListener listener) { 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCheckedChangeListener = listener; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when the checked state of this button 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * changes. This callback is used for internal purpose only. 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the callback to call on checked state change 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnCheckedChangeWidgetListener = listener; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Interface definition for a callback to be invoked when the checked state 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of a compound button changed. 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static interface OnCheckedChangeListener { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called when the checked state of a compound button has changed. 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param buttonView The compound button view whose state has changed. 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isChecked The new checked state of buttonView. 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onCheckedChanged(CompoundButton buttonView, boolean isChecked); 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 given its resource 2206a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * identifier. 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2226a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @param resId the resource identifier of the drawable 2236a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @attr ref android.R.styleable#CompoundButton_button 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2256a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette public void setButtonDrawable(@DrawableRes int resId) { 2266a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette final Drawable d; 2276a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette if (resId != 0) { 2286a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette d = getContext().getDrawable(resId); 2296a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette } else { 2306a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette d = null; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setButtonDrawable(d); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2366a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * Sets a drawable as the compound button image. 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2386a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @param drawable the drawable to set 2396a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @attr ref android.R.styleable#CompoundButton_button 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2416a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette public void setButtonDrawable(@Nullable Drawable drawable) { 2426a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette if (mButtonDrawable != drawable) { 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mButtonDrawable != null) { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mButtonDrawable.setCallback(null); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unscheduleDrawable(mButtonDrawable); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 247911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 2486a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette mButtonDrawable = drawable; 249911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 2506a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette if (drawable != null) { 2516a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette drawable.setCallback(this); 2526a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette drawable.setLayoutDirection(getLayoutDirection()); 2536a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette if (drawable.isStateful()) { 2546a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette drawable.setState(getDrawableState()); 255911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 2566a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette drawable.setVisible(getVisibility() == VISIBLE, false); 2576a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette setMinHeight(drawable.getIntrinsicHeight()); 258911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette applyButtonTint(); 259911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 261911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 263911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 2643380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu * @hide 2653380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu */ 2663380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu @Override 2673380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { 2683380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu super.onResolveDrawables(layoutDirection); 2693380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu if (mButtonDrawable != null) { 2703380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu mButtonDrawable.setLayoutDirection(layoutDirection); 2713380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu } 2723380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu } 2733380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu 2743380e69f5529972ff03b545353d5f1c5e2abc1b1Doris Liu /** 2756a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @return the drawable used as the compound button image 2766a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @see #setButtonDrawable(Drawable) 2776a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette * @see #setButtonDrawable(int) 2786a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette */ 2796a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette @Nullable 2806a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette public Drawable getButtonDrawable() { 2816a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette return mButtonDrawable; 2826a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette } 2836a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette 2846a394f4def305560c9b7ca3a14b3a313556db36eAlan Viverette /** 2854f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * Applies a tint to the button drawable. Does not modify the current tint 286b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 287911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * <p> 288911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * Subsequent calls to {@link #setButtonDrawable(Drawable)} will 289911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * automatically mutate the drawable and apply the specified tint and tint 290911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * mode using 291a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * {@link Drawable#setTintList(ColorStateList)}. 292911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 293911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @param tint the tint to apply, may be {@code null} to clear tint 294911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 295911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#CompoundButton_buttonTint 296a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see #setButtonTintList(ColorStateList) 297a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see Drawable#setTintList(ColorStateList) 298911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 299a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setButtonTintList(@Nullable ColorStateList tint) { 300a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mButtonTintList = tint; 301911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mHasButtonTint = true; 302911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 303911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette applyButtonTint(); 304911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 305911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 306911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 307911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @return the tint applied to the button drawable 308911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#CompoundButton_buttonTint 309a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see #setButtonTintList(ColorStateList) 310911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 311911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette @Nullable 312a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public ColorStateList getButtonTintList() { 313a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette return mButtonTintList; 314911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 315911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 316911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 317911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * Specifies the blending mode used to apply the tint specified by 318a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * {@link #setButtonTintList(ColorStateList)}} to the button drawable. The 319b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * default mode is {@link PorterDuff.Mode#SRC_IN}. 320911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 321911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @param tintMode the blending mode used to apply the tint, may be 322911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * {@code null} to clear tint 323911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#CompoundButton_buttonTintMode 3244f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @see #getButtonTintMode() 325a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see Drawable#setTintMode(PorterDuff.Mode) 326911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 327911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette public void setButtonTintMode(@Nullable PorterDuff.Mode tintMode) { 3284f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette mButtonTintMode = tintMode; 329b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mHasButtonTintMode = true; 3304f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette 3314f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette applyButtonTint(); 332911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 333911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 334911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 335911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @return the blending mode used to apply the tint to the button drawable 336911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#CompoundButton_buttonTintMode 3374f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @see #setButtonTintMode(PorterDuff.Mode) 338911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 339911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette @Nullable 340911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette public PorterDuff.Mode getButtonTintMode() { 341911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette return mButtonTintMode; 342911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 343911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 344911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette private void applyButtonTint() { 345b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mButtonDrawable != null && (mHasButtonTint || mHasButtonTintMode)) { 346911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mButtonDrawable = mButtonDrawable.mutate(); 347b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 348b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mHasButtonTint) { 349b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mButtonDrawable.setTintList(mButtonTintList); 350b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 351b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 352b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mHasButtonTintMode) { 353b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mButtonDrawable.setTintMode(mButtonTintMode); 354b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 355d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette 356d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette // The drawable (or one of its children) may not have been 357d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette // stateful before applying the tint, so let's try again. 358d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette if (mButtonDrawable.isStateful()) { 359d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette mButtonDrawable.setState(getDrawableState()); 360d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette } 361911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 364a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn @Override 365a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn public CharSequence getAccessibilityClassName() { 366a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn return CompoundButton.class.getName(); 367a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn } 368a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn 369a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 371a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 372a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onInitializeAccessibilityEventInternal(event); 373736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov event.setChecked(mChecked); 374cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru } 375cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru 376a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 377cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru @Override 378a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 379a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onInitializeAccessibilityNodeInfoInternal(info); 3800f55cc33f658b2793a12d609a0989348077324a4Svetoslav Ganov info.setCheckable(true); 38113774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganov info.setChecked(mChecked); 38213774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganov } 38313774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganov 38413774d2e38e73ef4d0f6d0db3501ba032fa6da5aSvetoslav Ganov @Override 3852842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio public int getCompoundPaddingLeft() { 3862842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio int padding = super.getCompoundPaddingLeft(); 3872842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio if (!isLayoutRtl()) { 3882842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio final Drawable buttonDrawable = mButtonDrawable; 3892842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio if (buttonDrawable != null) { 3902842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio padding += buttonDrawable.getIntrinsicWidth(); 3912842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3922842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3932842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio return padding; 3942842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 3952842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio 3962842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio @Override 3972842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio public int getCompoundPaddingRight() { 3982842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio int padding = super.getCompoundPaddingRight(); 3992842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio if (isLayoutRtl()) { 4002842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio final Drawable buttonDrawable = mButtonDrawable; 4012842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio if (buttonDrawable != null) { 4022842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio padding += buttonDrawable.getIntrinsicWidth(); 4032842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 4042842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 4052842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio return padding; 4062842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio } 4072842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio 408b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio /** 409b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio * @hide 410b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio */ 411b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio @Override 412b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio public int getHorizontalOffsetForDrawables() { 413b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio final Drawable buttonDrawable = mButtonDrawable; 414b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio return (buttonDrawable != null) ? buttonDrawable.getIntrinsicWidth() : 0; 415b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio } 416b878ddb56ec4e755706890110d76735176ff2295Fabrice Di Meglio 4172842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio @Override 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onDraw(Canvas canvas) { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Drawable buttonDrawable = mButtonDrawable; 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buttonDrawable != null) { 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; 4222842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio final int drawableHeight = buttonDrawable.getIntrinsicHeight(); 4232842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio final int drawableWidth = buttonDrawable.getIntrinsicWidth(); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42561956606818918194a38e045a8e35e7108480e5eAlan Viverette final int top; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (verticalGravity) { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case Gravity.BOTTOM: 4282842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio top = getHeight() - drawableHeight; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case Gravity.CENTER_VERTICAL: 4312842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio top = (getHeight() - drawableHeight) / 2; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 43361956606818918194a38e045a8e35e7108480e5eAlan Viverette default: 43461956606818918194a38e045a8e35e7108480e5eAlan Viverette top = 0; 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 43661956606818918194a38e045a8e35e7108480e5eAlan Viverette final int bottom = top + drawableHeight; 43761956606818918194a38e045a8e35e7108480e5eAlan Viverette final int left = isLayoutRtl() ? getWidth() - drawableWidth : 0; 43861956606818918194a38e045a8e35e7108480e5eAlan Viverette final int right = isLayoutRtl() ? getWidth() : drawableWidth; 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4402842679d3426295b6674dfcfb8591fad79de6cb2Fabrice Di Meglio buttonDrawable.setBounds(left, top, right, bottom); 44161956606818918194a38e045a8e35e7108480e5eAlan Viverette 44261956606818918194a38e045a8e35e7108480e5eAlan Viverette final Drawable background = getBackground(); 443c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette if (background != null) { 44461956606818918194a38e045a8e35e7108480e5eAlan Viverette background.setHotspotBounds(left, top, right, bottom); 44561956606818918194a38e045a8e35e7108480e5eAlan Viverette } 44661956606818918194a38e045a8e35e7108480e5eAlan Viverette } 44761956606818918194a38e045a8e35e7108480e5eAlan Viverette 44861956606818918194a38e045a8e35e7108480e5eAlan Viverette super.onDraw(canvas); 44961956606818918194a38e045a8e35e7108480e5eAlan Viverette 45061956606818918194a38e045a8e35e7108480e5eAlan Viverette if (buttonDrawable != null) { 451b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette final int scrollX = mScrollX; 452b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette final int scrollY = mScrollY; 453b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette if (scrollX == 0 && scrollY == 0) { 454b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette buttonDrawable.draw(canvas); 455b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette } else { 456b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette canvas.translate(scrollX, scrollY); 457b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette buttonDrawable.draw(canvas); 458b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette canvas.translate(-scrollX, -scrollY); 459b95c336d7863e6b63e2aa8682a90dd8ae213889cAlan Viverette } 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int[] onCreateDrawableState(int extraSpace) { 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isChecked()) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mergeDrawableStates(drawableState, CHECKED_STATE_SET); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return drawableState; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void drawableStateChanged() { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.drawableStateChanged(); 475ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette 476ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette final Drawable buttonDrawable = mButtonDrawable; 477ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette if (buttonDrawable != null && buttonDrawable.isStateful() 478ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette && buttonDrawable.setState(getDrawableState())) { 479ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette invalidateDrawable(buttonDrawable); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 483cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette @Override 4848de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette public void drawableHotspotChanged(float x, float y) { 4858de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette super.drawableHotspotChanged(x, y); 486cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette 487cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette if (mButtonDrawable != null) { 488cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette mButtonDrawable.setHotspot(x, y); 489cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette } 490cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette } 491cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 493f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette protected boolean verifyDrawable(@NonNull Drawable who) { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.verifyDrawable(who) || who == mButtonDrawable; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 497e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn @Override 498e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn public void jumpDrawablesToCurrentState() { 499e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn super.jumpDrawablesToCurrentState(); 500e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState(); 501e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn } 502e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class SavedState extends BaseSavedState { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean checked; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link CompoundButton#onSaveInstanceState()} 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState(Parcelable superState) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(superState); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 51299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link #CREATOR} 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SavedState(Parcel in) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(in); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checked = (Boolean)in.readValue(null); 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void writeToParcel(Parcel out, int flags) { 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.writeToParcel(out, flags); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeValue(checked); 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "CompoundButton.SavedState{" 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Integer.toHexString(System.identityHashCode(this)) 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " checked=" + checked + "}"; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5346d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @SuppressWarnings("hiding") 5356d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme public static final Parcelable.Creator<SavedState> CREATOR = 5366d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme new Parcelable.Creator<SavedState>() { 5376d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState createFromParcel(Parcel in) { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(in); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5426d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState[] newArray(int size) { 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState[size]; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Parcelable onSaveInstanceState() { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcelable superState = super.onSaveInstanceState(); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState ss = new SavedState(superState); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ss.checked = isChecked(); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ss; 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onRestoreInstanceState(Parcelable state) { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState ss = (SavedState) state; 56294a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onRestoreInstanceState(ss.getSuperState()); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setChecked(ss.checked); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 56794a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy 56894a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy /** @hide */ 56994a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy @Override 57094a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { 57194a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy super.encodeProperties(stream); 57294a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy stream.addProperty("checked", isChecked()); 57394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy } 5746d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 575640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme // TODO(b/33197203): add unit/CTS tests for autofill methods (and make sure they handle enable) 5766d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 5770200d9ea1509089c0c03b7071aa271e3a9b35c11Felipe Leme @Override 578640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme public void onProvideAutofillStructure(ViewStructure structure, int flags) { 579640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme super.onProvideAutofillStructure(structure, flags); 580c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme 581c9a19b1b274af1fdd8b811c9ce2df994f7db47a4Felipe Leme structure.setDataIsSensitive(!mCheckedFromResource); 582c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme } 583c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme 584c01a873c4f68518be4698077c7eb593a6a3b9f4cFelipe Leme @Override 585640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme public void autofill(AutofillValue value) { 586bab851c7c9dfe6f3d063a1009c4d57cfa2ff005cFelipe Leme if (!isEnabled()) return; 587bab851c7c9dfe6f3d063a1009c4d57cfa2ff005cFelipe Leme 5886d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme setChecked(value.getToggleValue()); 5896d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 5906d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 5916d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 5928931e303700a5adb6e013c2b5a6cec621eede968Felipe Leme public @AutofillType int getAutofillType() { 5938931e303700a5adb6e013c2b5a6cec621eede968Felipe Leme return isEnabled() ? AUTOFILL_TYPE_TOGGLE : AUTOFILL_TYPE_NONE; 5946d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 595bab851c7c9dfe6f3d063a1009c4d57cfa2ff005cFelipe Leme 596bab851c7c9dfe6f3d063a1009c4d57cfa2ff005cFelipe Leme @Override 597640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme public AutofillValue getAutofillValue() { 598640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme return isEnabled() ? AutofillValue.forToggle(isChecked()) : null; 599bab851c7c9dfe6f3d063a1009c4d57cfa2ff005cFelipe Leme } 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 601