112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell/* 212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Copyright (C) 2010 The Android Open Source Project 312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * you may not use this file except in compliance with the License. 612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * You may obtain a copy of the License at 712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * http://www.apache.org/licenses/LICENSE-2.0 912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 1012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Unless required by applicable law or agreed to in writing, software 1112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * distributed under the License is distributed on an "AS IS" BASIS, 1212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * See the License for the specific language governing permissions and 1412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * limitations under the License. 1512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 1612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 1712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellpackage android.widget; 1812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 19cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viveretteimport android.animation.ObjectAnimator; 207b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbyeimport android.annotation.DrawableRes; 21f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viveretteimport android.annotation.NonNull; 22e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viveretteimport android.annotation.Nullable; 237b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbyeimport android.annotation.StyleRes; 2412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.Context; 2512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.ColorStateList; 2612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.Resources; 2712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.TypedArray; 2812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Canvas; 29661e63658da39cccfe49a129e4860455716ff3c9Alan Viveretteimport android.graphics.Insets; 306a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craikimport android.graphics.Paint; 31e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viveretteimport android.graphics.PorterDuff; 3212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Rect; 33661e63658da39cccfe49a129e4860455716ff3c9Alan Viveretteimport android.graphics.Region.Op; 3499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport android.graphics.Typeface; 3512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.drawable.Drawable; 3612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.Layout; 3712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.StaticLayout; 3812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.TextPaint; 3912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.TextUtils; 404c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandlerimport android.text.method.AllCapsTransformationMethod; 414c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandlerimport android.text.method.TransformationMethod2; 4212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.util.AttributeSet; 43cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viveretteimport android.util.FloatProperty; 44cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viveretteimport android.util.MathUtils; 4512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.Gravity; 4612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.MotionEvent; 47d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viveretteimport android.view.SoundEffectConstants; 4812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.VelocityTracker; 4912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.ViewConfiguration; 5099441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport android.view.ViewStructure; 5163bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 528a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 5312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 54be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powellimport com.android.internal.R; 55be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powell 5612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell/** 5712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * A Switch is a two-state toggle switch widget that can select between two 5812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * options. The user may drag the "thumb" back and forth to choose the selected option, 59150176d83023e3c486dba10edebb72af36b4099aChet Haase * or simply tap to toggle as if it were a checkbox. The {@link #setText(CharSequence) text} 60150176d83023e3c486dba10edebb72af36b4099aChet Haase * property controls the text displayed in the label for the switch, whereas the 61150176d83023e3c486dba10edebb72af36b4099aChet Haase * {@link #setTextOff(CharSequence) off} and {@link #setTextOn(CharSequence) on} text 62150176d83023e3c486dba10edebb72af36b4099aChet Haase * controls the text on the thumb. Similarly, the 63150176d83023e3c486dba10edebb72af36b4099aChet Haase * {@link #setTextAppearance(android.content.Context, int) textAppearance} and the related 64150176d83023e3c486dba10edebb72af36b4099aChet Haase * setTypeface() methods control the typeface and style of label text, whereas the 65150176d83023e3c486dba10edebb72af36b4099aChet Haase * {@link #setSwitchTextAppearance(android.content.Context, int) switchTextAppearance} and 6607e7021e062dd3579f662502b15c0682c4672cfeAndrew Solovay * the related setSwitchTypeface() methods control that of the thumb. 6712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 683404032dfc3ef9130806de62289da27b3de0be46Mark Lu * <p>{@link android.support.v7.widget.SwitchCompat} is a version of 693404032dfc3ef9130806de62289da27b3de0be46Mark Lu * the Switch widget which runs on devices back to API 7.</p> 703404032dfc3ef9130806de62289da27b3de0be46Mark Lu * 714c359b76f9a030f92a302ba74a528faa170bad4eScott Main * <p>See the <a href="{@docRoot}guide/topics/ui/controls/togglebutton.html">Toggle Buttons</a> 724c359b76f9a030f92a302ba74a528faa170bad4eScott Main * guide.</p> 734c359b76f9a030f92a302ba74a528faa170bad4eScott Main * 744c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_textOn 754c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_textOff 764c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_switchMinWidth 774c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_switchPadding 784c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_switchTextAppearance 794c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_thumb 804c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_thumbTextPadding 814c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_track 8212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 8312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellpublic class Switch extends CompoundButton { 84cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette private static final int THUMB_ANIMATION_DURATION = 250; 85cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 8612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int TOUCH_MODE_IDLE = 0; 8712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int TOUCH_MODE_DOWN = 1; 8812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int TOUCH_MODE_DRAGGING = 2; 8912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 9012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Enum for the "typeface" XML parameter. 9112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int SANS = 1; 9212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int SERIF = 2; 9312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int MONOSPACE = 3; 9412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 9512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Drawable mThumbDrawable; 96e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private ColorStateList mThumbTintList = null; 97e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private PorterDuff.Mode mThumbTintMode = null; 98e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private boolean mHasThumbTint = false; 99e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private boolean mHasThumbTintMode = false; 100e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 10112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Drawable mTrackDrawable; 102e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private ColorStateList mTrackTintList = null; 103e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private PorterDuff.Mode mTrackTintMode = null; 104e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private boolean mHasTrackTint = false; 105e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private boolean mHasTrackTintMode = false; 106e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 10712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mThumbTextPadding; 10812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchMinWidth; 10912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchPadding; 110661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette private boolean mSplitTrack; 11112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private CharSequence mTextOn; 11212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private CharSequence mTextOff; 1132a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette private boolean mShowText; 11412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 11512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mTouchMode; 11612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mTouchSlop; 11712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private float mTouchX; 11812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private float mTouchY; 11912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private VelocityTracker mVelocityTracker = VelocityTracker.obtain(); 12012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mMinFlingVelocity; 12112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 12212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private float mThumbPosition; 1230c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 1240c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette /** 1250c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * Width required to draw the switch track and thumb. Includes padding and 1260c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * optical bounds for both the track and thumb. 1270c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette */ 12812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchWidth; 1290c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 1300c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette /** 1310c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * Height required to draw the switch track and thumb. Includes padding and 1320c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * optical bounds for both the track and thumb. 1330c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette */ 13412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchHeight; 13512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 1360c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette /** 1370c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * Width of the thumb's content region. Does not include padding or 1380c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * optical bounds. 1390c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette */ 1400c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette private int mThumbWidth; 1410c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 1420c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette /** Left bound for drawing the switch track and thumb. */ 14312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchLeft; 1440c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 1450c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette /** Top bound for drawing the switch track and thumb. */ 14612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchTop; 1470c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 1480c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette /** Right bound for drawing the switch track and thumb. */ 14912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchRight; 1500c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 1510c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette /** Bottom bound for drawing the switch track and thumb. */ 15212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchBottom; 15312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 15412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private TextPaint mTextPaint; 15512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private ColorStateList mTextColors; 15612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Layout mOnLayout; 15712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Layout mOffLayout; 1584c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler private TransformationMethod2 mSwitchTransformationMethod; 159cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette private ObjectAnimator mPositionAnimator; 16012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 161be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powell @SuppressWarnings("hiding") 16212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private final Rect mTempRect = new Rect(); 16312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 16412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int[] CHECKED_STATE_SET = { 16512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell R.attr.state_checked 16612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell }; 16712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 16812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 16912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Construct a new Switch with default styling. 17012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 17112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param context The Context that will determine this widget's theming. 17212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 17312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public Switch(Context context) { 17412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell this(context, null); 17512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 17612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 17712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 17812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Construct a new Switch with default styling, overriding specific style 17912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * attributes as requested. 18012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 18112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param context The Context that will determine this widget's theming. 18212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param attrs Specification of attributes that should deviate from default styling. 18312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 18412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public Switch(Context context, AttributeSet attrs) { 18512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell this(context, attrs, com.android.internal.R.attr.switchStyle); 18612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 18712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 18812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 18912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Construct a new Switch with a default style determined by the given theme attribute, 19012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * overriding specific style attributes as requested. 19112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 19212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param context The Context that will determine this widget's theming. 19312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param attrs Specification of attributes that should deviate from the default styling. 194617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 195617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * reference to a style resource that supplies default values for 196617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * the view. Can be 0 to not look for defaults. 19712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 198617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public Switch(Context context, AttributeSet attrs, int defStyleAttr) { 199617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 200617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 201617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 202617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 203617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette /** 204617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * Construct a new Switch with a default style determined by the given theme 205617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * attribute or style resource, overriding specific style attributes as 206617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * requested. 207617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * 208617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param context The Context that will determine this widget's theming. 209617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param attrs Specification of attributes that should deviate from the 210617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * default styling. 211617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 212617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * reference to a style resource that supplies default values for 213617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * the view. Can be 0 to not look for defaults. 214617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleRes A resource identifier of a style resource that 215617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * supplies default values for the view, used only if 216617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * defStyleAttr is 0 or can not be found in the theme. Can be 0 217617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * to not look for defaults. 218617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette */ 219617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public Switch(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 220617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 22112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 2226a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); 223661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 224661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Resources res = getResources(); 22512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.density = res.getDisplayMetrics().density; 22612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale); 22712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 228617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette final TypedArray a = context.obtainStyledAttributes( 229617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette attrs, com.android.internal.R.styleable.Switch, defStyleAttr, defStyleRes); 230150176d83023e3c486dba10edebb72af36b4099aChet Haase mThumbDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_thumb); 231b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette if (mThumbDrawable != null) { 232b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette mThumbDrawable.setCallback(this); 233b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette } 234150176d83023e3c486dba10edebb72af36b4099aChet Haase mTrackDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_track); 235b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette if (mTrackDrawable != null) { 236b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette mTrackDrawable.setCallback(this); 237b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette } 23812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextOn = a.getText(com.android.internal.R.styleable.Switch_textOn); 23912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextOff = a.getText(com.android.internal.R.styleable.Switch_textOff); 2402a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette mShowText = a.getBoolean(com.android.internal.R.styleable.Switch_showText, true); 24112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbTextPadding = a.getDimensionPixelSize( 24212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch_thumbTextPadding, 0); 24312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchMinWidth = a.getDimensionPixelSize( 24412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch_switchMinWidth, 0); 24512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchPadding = a.getDimensionPixelSize( 24612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch_switchPadding, 0); 247661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette mSplitTrack = a.getBoolean(com.android.internal.R.styleable.Switch_splitTrack, false); 24812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 2499fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai ColorStateList thumbTintList = a.getColorStateList( 2509fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai com.android.internal.R.styleable.Switch_thumbTint); 2519fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai if (thumbTintList != null) { 2529fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai mThumbTintList = thumbTintList; 2539fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai mHasThumbTint = true; 2549fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai } 2559fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai PorterDuff.Mode thumbTintMode = Drawable.parseTintMode( 2569fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai a.getInt(com.android.internal.R.styleable.Switch_thumbTintMode, -1), null); 2579fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai if (mThumbTintMode != thumbTintMode) { 2589fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai mThumbTintMode = thumbTintMode; 2599fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai mHasThumbTintMode = true; 2609fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai } 2619fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai if (mHasThumbTint || mHasThumbTintMode) { 2629fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai applyThumbTint(); 2639fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai } 2649fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai 2659fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai ColorStateList trackTintList = a.getColorStateList( 2669fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai com.android.internal.R.styleable.Switch_trackTint); 2679fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai if (trackTintList != null) { 2689fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai mTrackTintList = trackTintList; 2699fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai mHasTrackTint = true; 2709fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai } 2719fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai PorterDuff.Mode trackTintMode = Drawable.parseTintMode( 2729fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai a.getInt(com.android.internal.R.styleable.Switch_trackTintMode, -1), null); 2739fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai if (mTrackTintMode != trackTintMode) { 2749fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai mTrackTintMode = trackTintMode; 2759fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai mHasTrackTintMode = true; 2769fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai } 2779fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai if (mHasTrackTint || mHasTrackTintMode) { 2789fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai applyTrackTint(); 2799fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai } 2809fb302cfbca57270250a33503791a85f2f5122f1Jun Mukai 281661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int appearance = a.getResourceId( 28212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch_switchTextAppearance, 0); 28312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (appearance != 0) { 284150176d83023e3c486dba10edebb72af36b4099aChet Haase setSwitchTextAppearance(context, appearance); 28512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 28612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell a.recycle(); 28712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 288661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final ViewConfiguration config = ViewConfiguration.get(context); 28912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchSlop = config.getScaledTouchSlop(); 29012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mMinFlingVelocity = config.getScaledMinimumFlingVelocity(); 29112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 29212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Refresh display with current params 293e724ee4b04d121556e9764f72f9b921a0e16392aGilles Debunne refreshDrawableState(); 29412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setChecked(isChecked()); 29512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 29612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 29712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 29812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Sets the switch text color, size, style, hint color, and highlight color 29912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * from the specified TextAppearance resource. 3006c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 3016c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_switchTextAppearance 30212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 3037b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye public void setSwitchTextAppearance(Context context, @StyleRes int resid) { 30412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TypedArray appearance = 305150176d83023e3c486dba10edebb72af36b4099aChet Haase context.obtainStyledAttributes(resid, 30612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.TextAppearance); 30712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 30812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell ColorStateList colors; 30912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int ts; 31012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 31112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell colors = appearance.getColorStateList(com.android.internal.R.styleable. 31212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TextAppearance_textColor); 31312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (colors != null) { 31412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextColors = colors; 315150176d83023e3c486dba10edebb72af36b4099aChet Haase } else { 316150176d83023e3c486dba10edebb72af36b4099aChet Haase // If no color set in TextAppearance, default to the view's textColor 317150176d83023e3c486dba10edebb72af36b4099aChet Haase mTextColors = getTextColors(); 31812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 31912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 32012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell ts = appearance.getDimensionPixelSize(com.android.internal.R.styleable. 32112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TextAppearance_textSize, 0); 32212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (ts != 0) { 32312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (ts != mTextPaint.getTextSize()) { 32412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setTextSize(ts); 32512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell requestLayout(); 32612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 32712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 32812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 32912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int typefaceIndex, styleIndex; 33012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 33112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell typefaceIndex = appearance.getInt(com.android.internal.R.styleable. 33212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TextAppearance_typeface, -1); 33312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell styleIndex = appearance.getInt(com.android.internal.R.styleable. 33412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TextAppearance_textStyle, -1); 33512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 33612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTypefaceByIndex(typefaceIndex, styleIndex); 33712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 3384c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler boolean allCaps = appearance.getBoolean(com.android.internal.R.styleable. 3394c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler TextAppearance_textAllCaps, false); 3404c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler if (allCaps) { 3414c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler mSwitchTransformationMethod = new AllCapsTransformationMethod(getContext()); 3424c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler mSwitchTransformationMethod.setLengthChangesAllowed(true); 3434c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler } else { 3444c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler mSwitchTransformationMethod = null; 3454c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler } 3464c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler 34712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell appearance.recycle(); 34812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 34912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 35012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private void setSwitchTypefaceByIndex(int typefaceIndex, int styleIndex) { 35112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Typeface tf = null; 35212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (typefaceIndex) { 35312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case SANS: 35412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.SANS_SERIF; 35512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 35612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 35712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case SERIF: 35812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.SERIF; 35912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 36012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 36112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MONOSPACE: 36212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.MONOSPACE; 36312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 36412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 36512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 36612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTypeface(tf, styleIndex); 36712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 36812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 36912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 37012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Sets the typeface and style in which the text should be displayed on the 37112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * switch, and turns on the fake bold and italic bits in the Paint if the 37212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Typeface that you provided does not have all the bits in the 37312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * style that you specified. 37412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 37512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setSwitchTypeface(Typeface tf, int style) { 37612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (style > 0) { 37712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (tf == null) { 37812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.defaultFromStyle(style); 37912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } else { 38012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.create(tf, style); 38112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 38212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 38312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTypeface(tf); 38412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // now compute what (if any) algorithmic styling is needed 38512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int typefaceStyle = tf != null ? tf.getStyle() : 0; 38612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int need = style & ~typefaceStyle; 38712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0); 38812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0); 38912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } else { 390aa0980afab57a6aebb06e70f60e92511708fa5afVictoria Lease mTextPaint.setFakeBoldText(false); 39112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setTextSkewX(0); 39212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTypeface(tf); 39312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 39412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 39512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 39612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 397150176d83023e3c486dba10edebb72af36b4099aChet Haase * Sets the typeface in which the text should be displayed on the switch. 39812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Note that not all Typeface families actually have bold and italic 39912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * variants, so you may need to use 40012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * {@link #setSwitchTypeface(Typeface, int)} to get the appearance 40112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * that you actually want. 40212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 40312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @attr ref android.R.styleable#TextView_typeface 40412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @attr ref android.R.styleable#TextView_textStyle 40512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 40612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setSwitchTypeface(Typeface tf) { 40712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (mTextPaint.getTypeface() != tf) { 40812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setTypeface(tf); 40912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 41012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell requestLayout(); 41112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell invalidate(); 41212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 41312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 41412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 41512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 4166c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Set the amount of horizontal padding between the switch and the associated text. 4176c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4186c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @param pixels Amount of padding in pixels 4196c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4206c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_switchPadding 4216c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 4226c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public void setSwitchPadding(int pixels) { 4236c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell mSwitchPadding = pixels; 4246c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell requestLayout(); 4256c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 4266c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 4276c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 4286c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Get the amount of horizontal padding between the switch and the associated text. 4296c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4306c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @return Amount of padding in pixels 4316c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4326c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_switchPadding 4336c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 4346c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public int getSwitchPadding() { 4356c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell return mSwitchPadding; 4366c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 4376c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 4386c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 4396c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Set the minimum width of the switch in pixels. The switch's width will be the maximum 4406c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * of this value and its measured width as determined by the switch drawables and text used. 4416c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4426c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @param pixels Minimum width of the switch in pixels 4436c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4446c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_switchMinWidth 4456c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 4466c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public void setSwitchMinWidth(int pixels) { 4476c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell mSwitchMinWidth = pixels; 4486c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell requestLayout(); 4496c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 4506c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 4516c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 4526c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Get the minimum width of the switch in pixels. The switch's width will be the maximum 4536c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * of this value and its measured width as determined by the switch drawables and text used. 4546c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4556c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @return Minimum width of the switch in pixels 4566c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4576c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_switchMinWidth 4586c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 4596c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public int getSwitchMinWidth() { 4606c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell return mSwitchMinWidth; 4616c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 4626c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 4636c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 4646c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Set the horizontal padding around the text drawn on the switch itself. 4656c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4666c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @param pixels Horizontal padding for switch thumb text in pixels 4676c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4686c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_thumbTextPadding 4696c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 4706c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public void setThumbTextPadding(int pixels) { 4716c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell mThumbTextPadding = pixels; 4726c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell requestLayout(); 4736c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 4746c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 4756c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 4766c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Get the horizontal padding around the text drawn on the switch itself. 4776c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4786c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @return Horizontal padding for switch thumb text in pixels 4796c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4806c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_thumbTextPadding 4816c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 4826c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public int getThumbTextPadding() { 4836c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell return mThumbTextPadding; 4846c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 4856c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 4866c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 4876c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Set the drawable used for the track that the switch slides within. 4886c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4896c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @param track Track drawable 4906c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 4916c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_track 4926c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 4936c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public void setTrackDrawable(Drawable track) { 494b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette if (mTrackDrawable != null) { 495b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette mTrackDrawable.setCallback(null); 496b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette } 4976c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell mTrackDrawable = track; 498b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette if (track != null) { 499b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette track.setCallback(this); 500b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette } 5016c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell requestLayout(); 5026c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 5036c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 5046c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 505d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Set the drawable used for the track that the switch slides within. 506d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 507dca510e026e3e75759bac84c3860dc84b83a608fAdam Powell * @param resId Resource ID of a track drawable 508d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 509d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @attr ref android.R.styleable#Switch_track 510d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 5117b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye public void setTrackResource(@DrawableRes int resId) { 5128eea3ea5591e59f55cbb4f6b2b7e9363a285ced3Alan Viverette setTrackDrawable(getContext().getDrawable(resId)); 513d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 514d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 515d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 5166c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Get the drawable used for the track that the switch slides within. 5176c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 5186c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @return Track drawable 5196c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 5206c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_track 5216c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 5226c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public Drawable getTrackDrawable() { 5236c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell return mTrackDrawable; 5246c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 5256c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 5266c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 527e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * Applies a tint to the track drawable. Does not modify the current 528e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 529e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * <p> 530e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * Subsequent calls to {@link #setTrackDrawable(Drawable)} will 531e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * automatically mutate the drawable and apply the specified tint and tint 532e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * mode using {@link Drawable#setTintList(ColorStateList)}. 533e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * 534e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @param tint the tint to apply, may be {@code null} to clear tint 535e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * 536e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @attr ref android.R.styleable#Switch_trackTint 537e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see #getTrackTintList() 538e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see Drawable#setTintList(ColorStateList) 539e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette */ 540e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette public void setTrackTintList(@Nullable ColorStateList tint) { 541e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mTrackTintList = tint; 542e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mHasTrackTint = true; 543e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 544e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette applyTrackTint(); 545e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 546e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 547e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette /** 548e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @return the tint applied to the track drawable 549e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @attr ref android.R.styleable#Switch_trackTint 550e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see #setTrackTintList(ColorStateList) 551e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette */ 552e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette @Nullable 553e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette public ColorStateList getTrackTintList() { 554e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette return mTrackTintList; 555e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 556e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 557e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette /** 558e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * Specifies the blending mode used to apply the tint specified by 559e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * {@link #setTrackTintList(ColorStateList)}} to the track drawable. 560e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * The default mode is {@link PorterDuff.Mode#SRC_IN}. 561e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * 562e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @param tintMode the blending mode used to apply the tint, may be 563e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * {@code null} to clear tint 564e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @attr ref android.R.styleable#Switch_trackTintMode 565e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see #getTrackTintMode() 566e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see Drawable#setTintMode(PorterDuff.Mode) 567e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette */ 568e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette public void setTrackTintMode(@Nullable PorterDuff.Mode tintMode) { 569e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mTrackTintMode = tintMode; 570e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mHasTrackTintMode = true; 571e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 572e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette applyTrackTint(); 573e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 574e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 575e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette /** 576e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @return the blending mode used to apply the tint to the track 577e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * drawable 578e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @attr ref android.R.styleable#Switch_trackTintMode 579e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see #setTrackTintMode(PorterDuff.Mode) 580e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette */ 581e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette @Nullable 582e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette public PorterDuff.Mode getTrackTintMode() { 583e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette return mTrackTintMode; 584e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 585e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 586e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private void applyTrackTint() { 587e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette if (mTrackDrawable != null && (mHasTrackTint || mHasTrackTintMode)) { 588e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mTrackDrawable = mTrackDrawable.mutate(); 589e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 590e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette if (mHasTrackTint) { 591e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mTrackDrawable.setTintList(mTrackTintList); 592e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 593e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 594e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette if (mHasTrackTintMode) { 595e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mTrackDrawable.setTintMode(mTrackTintMode); 596e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 597e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 598e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette // The drawable (or one of its children) may not have been 599e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette // stateful before applying the tint, so let's try again. 600e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette if (mTrackDrawable.isStateful()) { 601e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mTrackDrawable.setState(getDrawableState()); 602e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 603e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 604e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 605e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 606e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette /** 6076c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Set the drawable used for the switch "thumb" - the piece that the user 6086c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * can physically touch and drag along the track. 6096c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 6106c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @param thumb Thumb drawable 6116c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 6126c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_thumb 6136c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 6146c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public void setThumbDrawable(Drawable thumb) { 615b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette if (mThumbDrawable != null) { 616b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette mThumbDrawable.setCallback(null); 617b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette } 6186c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell mThumbDrawable = thumb; 619b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette if (thumb != null) { 620b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette thumb.setCallback(this); 621b067405bf453289a6b6bfd34b06700f08be58c24Alan Viverette } 6226c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell requestLayout(); 6236c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 6246c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 6256c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 626d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Set the drawable used for the switch "thumb" - the piece that the user 627d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * can physically touch and drag along the track. 628d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 629dca510e026e3e75759bac84c3860dc84b83a608fAdam Powell * @param resId Resource ID of a thumb drawable 630d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 631d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @attr ref android.R.styleable#Switch_thumb 632d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 6337b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye public void setThumbResource(@DrawableRes int resId) { 6348eea3ea5591e59f55cbb4f6b2b7e9363a285ced3Alan Viverette setThumbDrawable(getContext().getDrawable(resId)); 635d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 636d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 637d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 6386c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * Get the drawable used for the switch "thumb" - the piece that the user 6396c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * can physically touch and drag along the track. 6406c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 6416c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @return Thumb drawable 6426c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 6436c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_thumb 6446c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell */ 6456c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell public Drawable getThumbDrawable() { 6466c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell return mThumbDrawable; 6476c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell } 6486c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell 6496c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell /** 650e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * Applies a tint to the thumb drawable. Does not modify the current 651e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 652e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * <p> 653e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * Subsequent calls to {@link #setThumbDrawable(Drawable)} will 654e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * automatically mutate the drawable and apply the specified tint and tint 655e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * mode using {@link Drawable#setTintList(ColorStateList)}. 656e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * 657e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @param tint the tint to apply, may be {@code null} to clear tint 658e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * 659e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @attr ref android.R.styleable#Switch_thumbTint 660e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see #getThumbTintList() 661e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see Drawable#setTintList(ColorStateList) 662e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette */ 663e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette public void setThumbTintList(@Nullable ColorStateList tint) { 664e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mThumbTintList = tint; 665e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mHasThumbTint = true; 666e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 667e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette applyThumbTint(); 668e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 669e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 670e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette /** 671e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @return the tint applied to the thumb drawable 672e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @attr ref android.R.styleable#Switch_thumbTint 673e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see #setThumbTintList(ColorStateList) 674e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette */ 675e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette @Nullable 676e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette public ColorStateList getThumbTintList() { 677e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette return mThumbTintList; 678e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 679e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 680e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette /** 681e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * Specifies the blending mode used to apply the tint specified by 682e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * {@link #setThumbTintList(ColorStateList)}} to the thumb drawable. 683e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * The default mode is {@link PorterDuff.Mode#SRC_IN}. 684e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * 685e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @param tintMode the blending mode used to apply the tint, may be 686e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * {@code null} to clear tint 687e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @attr ref android.R.styleable#Switch_thumbTintMode 688e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see #getThumbTintMode() 689e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see Drawable#setTintMode(PorterDuff.Mode) 690e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette */ 691e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette public void setThumbTintMode(@Nullable PorterDuff.Mode tintMode) { 692e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mThumbTintMode = tintMode; 693e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mHasThumbTintMode = true; 694e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 695e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette applyThumbTint(); 696e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 697e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 698e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette /** 699e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @return the blending mode used to apply the tint to the thumb 700e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * drawable 701e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @attr ref android.R.styleable#Switch_thumbTintMode 702e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette * @see #setThumbTintMode(PorterDuff.Mode) 703e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette */ 704e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette @Nullable 705e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette public PorterDuff.Mode getThumbTintMode() { 706e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette return mThumbTintMode; 707e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 708e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 709e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette private void applyThumbTint() { 710e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette if (mThumbDrawable != null && (mHasThumbTint || mHasThumbTintMode)) { 711e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mThumbDrawable = mThumbDrawable.mutate(); 712e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 713e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette if (mHasThumbTint) { 714e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mThumbDrawable.setTintList(mThumbTintList); 715e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 716e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 717e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette if (mHasThumbTintMode) { 718e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mThumbDrawable.setTintMode(mThumbTintMode); 719e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 720e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 721e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette // The drawable (or one of its children) may not have been 722e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette // stateful before applying the tint, so let's try again. 723e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette if (mThumbDrawable.isStateful()) { 724e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette mThumbDrawable.setState(getDrawableState()); 725e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 726e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 727e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette } 728e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette 729e7eee640f83b0cffef63ef1f196efa4dcac64095Alan Viverette /** 730661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * Specifies whether the track should be split by the thumb. When true, 731661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * the thumb's optical bounds will be clipped out of the track drawable, 732661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * then the thumb will be drawn into the resulting gap. 733661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 734661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * @param splitTrack Whether the track should be split by the thumb 735661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 736661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * @attr ref android.R.styleable#Switch_splitTrack 737661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette */ 738661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette public void setSplitTrack(boolean splitTrack) { 739661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette mSplitTrack = splitTrack; 740661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette invalidate(); 741661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 742661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 743661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette /** 744661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * Returns whether the track should be split by the thumb. 745661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 746661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * @attr ref android.R.styleable#Switch_splitTrack 747661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette */ 748661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette public boolean getSplitTrack() { 749661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette return mSplitTrack; 750661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 751661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 752661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette /** 753150176d83023e3c486dba10edebb72af36b4099aChet Haase * Returns the text displayed when the button is in the checked state. 7546c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 7556c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_textOn 75612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 75712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public CharSequence getTextOn() { 75812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return mTextOn; 75912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 76012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 76112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 762150176d83023e3c486dba10edebb72af36b4099aChet Haase * Sets the text displayed when the button is in the checked state. 7636c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 7646c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_textOn 76512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 76612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setTextOn(CharSequence textOn) { 76712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextOn = textOn; 76812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell requestLayout(); 76912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 77012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 77112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 772150176d83023e3c486dba10edebb72af36b4099aChet Haase * Returns the text displayed when the button is not in the checked state. 7736c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 7746c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_textOff 77512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 77612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public CharSequence getTextOff() { 77712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return mTextOff; 77812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 77912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 78012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 781150176d83023e3c486dba10edebb72af36b4099aChet Haase * Sets the text displayed when the button is not in the checked state. 7826c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * 7836c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell * @attr ref android.R.styleable#Switch_textOff 78412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 78512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setTextOff(CharSequence textOff) { 78612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextOff = textOff; 78712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell requestLayout(); 78812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 78912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 7902a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette /** 7912a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette * Sets whether the on/off text should be displayed. 7922a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette * 7932a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette * @param showText {@code true} to display on/off text 7940c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * @attr ref android.R.styleable#Switch_showText 7952a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette */ 7962a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette public void setShowText(boolean showText) { 7972a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette if (mShowText != showText) { 7982a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette mShowText = showText; 7992a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette requestLayout(); 8002a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette } 8012a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette } 8022a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette 8032a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette /** 8042a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette * @return whether the on/off text should be displayed 8050c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * @attr ref android.R.styleable#Switch_showText 8062a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette */ 8072a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette public boolean getShowText() { 8082a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette return mShowText; 8092a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette } 8102a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette 81112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 81212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 8132a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette if (mShowText) { 8142a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette if (mOnLayout == null) { 8152a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette mOnLayout = makeLayout(mTextOn); 8162a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette } 8175876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette 8182a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette if (mOffLayout == null) { 8192a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette mOffLayout = makeLayout(mTextOff); 8202a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette } 82112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 82212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 8239b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette final Rect padding = mTempRect; 8249b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette final int thumbWidth; 8259b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette final int thumbHeight; 8268bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette if (mThumbDrawable != null) { 8270c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette // Cached thumb width does not include padding. 8280c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette mThumbDrawable.getPadding(padding); 8290c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette thumbWidth = mThumbDrawable.getIntrinsicWidth() - padding.left - padding.right; 8309b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette thumbHeight = mThumbDrawable.getIntrinsicHeight(); 8319b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette } else { 8329b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette thumbWidth = 0; 8339b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette thumbHeight = 0; 8348bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette } 8358bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette 8360c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final int maxTextWidth; 8370c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (mShowText) { 8380c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth()) 8390c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette + mThumbTextPadding * 2; 8400c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } else { 8410c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette maxTextWidth = 0; 8420c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 8430c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 8449b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette mThumbWidth = Math.max(maxTextWidth, thumbWidth); 8459b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette 8460c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final int trackHeight; 8470c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (mTrackDrawable != null) { 8480c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette mTrackDrawable.getPadding(padding); 8490c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette trackHeight = mTrackDrawable.getIntrinsicHeight(); 8500c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } else { 8510c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette padding.setEmpty(); 8520c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette trackHeight = 0; 8530c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 8540c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 8550c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette // Adjust left and right padding to ensure there's enough room for the 8560c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette // thumb's padding (when present). 8570c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int paddingLeft = padding.left; 8580c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int paddingRight = padding.right; 8590c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (mThumbDrawable != null) { 8600c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final Insets inset = mThumbDrawable.getOpticalInsets(); 8610c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette paddingLeft = Math.max(paddingLeft, inset.left); 8620c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette paddingRight = Math.max(paddingRight, inset.right); 8630c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 8640c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 86512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int switchWidth = Math.max(mSwitchMinWidth, 8660c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 2 * mThumbWidth + paddingLeft + paddingRight); 8674d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final int switchHeight = Math.max(trackHeight, thumbHeight); 86812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchWidth = switchWidth; 86912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchHeight = switchHeight; 87012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 87112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.onMeasure(widthMeasureSpec, heightMeasureSpec); 8724d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 87312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int measuredHeight = getMeasuredHeight(); 87412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (measuredHeight < switchHeight) { 875189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn setMeasuredDimension(getMeasuredWidthAndState(), switchHeight); 87612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 87712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 87812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 879a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 88063bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov @Override 881a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 882a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onPopulateAccessibilityEventInternal(event); 8832a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette 8842a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette final CharSequence text = isChecked() ? mTextOn : mTextOff; 8852a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette if (text != null) { 8862a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette event.getText().add(text); 8877650259a597dd24137420d32acc35efc44db381eSvetoslav Ganov } 88863bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov } 88963bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov 89012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Layout makeLayout(CharSequence text) { 8914c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler final CharSequence transformed = (mSwitchTransformationMethod != null) 8924c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler ? mSwitchTransformationMethod.getTransformation(text, this) 8934c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler : text; 8944c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler 89579bf9d19f2f76cbfbd6659c9323e519deaa887c7Siyamed Sinir int width = (int) Math.ceil(Layout.getDesiredWidth(transformed, 0, 89679bf9d19f2f76cbfbd6659c9323e519deaa887c7Siyamed Sinir transformed.length(), mTextPaint, getTextDirectionHeuristic())); 89779bf9d19f2f76cbfbd6659c9323e519deaa887c7Siyamed Sinir return new StaticLayout(transformed, mTextPaint, width, 89812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true); 89912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 90012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 90112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 90212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @return true if (x, y) is within the target area of the switch thumb 90312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 90412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private boolean hitThumb(float x, float y) { 90501a09630060eccc471ba3d8d83b34a602871d5c1Alan Viverette if (mThumbDrawable == null) { 90601a09630060eccc471ba3d8d83b34a602871d5c1Alan Viverette return false; 90701a09630060eccc471ba3d8d83b34a602871d5c1Alan Viverette } 90801a09630060eccc471ba3d8d83b34a602871d5c1Alan Viverette 909cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette // Relies on mTempRect, MUST be called first! 910cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette final int thumbOffset = getThumbOffset(); 911cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 91212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbDrawable.getPadding(mTempRect); 91312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int thumbTop = mSwitchTop - mTouchSlop; 914cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette final int thumbLeft = mSwitchLeft + thumbOffset - mTouchSlop; 91512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int thumbRight = thumbLeft + mThumbWidth + 91612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTempRect.left + mTempRect.right + mTouchSlop; 91712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int thumbBottom = mSwitchBottom + mTouchSlop; 91812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return x > thumbLeft && x < thumbRight && y > thumbTop && y < thumbBottom; 91912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 92012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 92112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 92212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public boolean onTouchEvent(MotionEvent ev) { 92312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mVelocityTracker.addMovement(ev); 92412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int action = ev.getActionMasked(); 92512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (action) { 92612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MotionEvent.ACTION_DOWN: { 92712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float x = ev.getX(); 92812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float y = ev.getY(); 929c2ab0d665c9d1c332fbd726abf582a27cf7a6701Gilles Debunne if (isEnabled() && hitThumb(x, y)) { 93012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchMode = TOUCH_MODE_DOWN; 93112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchX = x; 93212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchY = y; 93312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 93412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 93512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 93612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 93712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MotionEvent.ACTION_MOVE: { 93812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (mTouchMode) { 93912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case TOUCH_MODE_IDLE: 94012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Didn't target the thumb, treat normally. 94112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 94212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 94312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case TOUCH_MODE_DOWN: { 94412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float x = ev.getX(); 94512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float y = ev.getY(); 94612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (Math.abs(x - mTouchX) > mTouchSlop || 94712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Math.abs(y - mTouchY) > mTouchSlop) { 94812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchMode = TOUCH_MODE_DRAGGING; 94912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell getParent().requestDisallowInterceptTouchEvent(true); 95012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchX = x; 95112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchY = y; 95212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return true; 95312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 95412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 95512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 95612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 95712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case TOUCH_MODE_DRAGGING: { 95812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float x = ev.getX(); 959cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette final int thumbScrollRange = getThumbScrollRange(); 960cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette final float thumbScrollOffset = x - mTouchX; 961cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette float dPos; 962cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette if (thumbScrollRange != 0) { 963cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette dPos = thumbScrollOffset / thumbScrollRange; 964cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } else { 965cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette // If the thumb scroll range is empty, just use the 966cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette // movement direction to snap on or off. 967cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette dPos = thumbScrollOffset > 0 ? 1 : -1; 968cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } 969cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette if (isLayoutRtl()) { 970cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette dPos = -dPos; 971cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } 972cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette final float newPos = MathUtils.constrain(mThumbPosition + dPos, 0, 1); 97312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (newPos != mThumbPosition) { 97412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchX = x; 975cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette setThumbPosition(newPos); 97612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 97712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return true; 97812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 97912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 98012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 98112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 98212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 98312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MotionEvent.ACTION_UP: 98412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MotionEvent.ACTION_CANCEL: { 98512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (mTouchMode == TOUCH_MODE_DRAGGING) { 98612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell stopDrag(ev); 987ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette // Allow super class to handle pressed state, etc. 988ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette super.onTouchEvent(ev); 98912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return true; 99012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 99112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchMode = TOUCH_MODE_IDLE; 99212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mVelocityTracker.clear(); 99312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 99412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 99512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 99612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 99712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return super.onTouchEvent(ev); 99812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 99912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 100012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private void cancelSuperTouch(MotionEvent ev) { 100112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell MotionEvent cancel = MotionEvent.obtain(ev); 100212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell cancel.setAction(MotionEvent.ACTION_CANCEL); 100312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.onTouchEvent(cancel); 100412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell cancel.recycle(); 100512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 100612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 100712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 100812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Called from onTouchEvent to end a drag operation. 100912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 101012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param ev Event that triggered the end of drag mode - ACTION_UP or ACTION_CANCEL 101112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 101212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private void stopDrag(MotionEvent ev) { 101312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchMode = TOUCH_MODE_IDLE; 101412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 101586453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette // Commit the change if the event is up and not canceled and the switch 101686453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette // has not been disabled during the drag. 101786453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette final boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP && isEnabled(); 1018d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette final boolean oldState = isChecked(); 101986453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette final boolean newState; 102012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (commitChange) { 102112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mVelocityTracker.computeCurrentVelocity(1000); 102286453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette final float xvel = mVelocityTracker.getXVelocity(); 102312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (Math.abs(xvel) > mMinFlingVelocity) { 102428efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio newState = isLayoutRtl() ? (xvel < 0) : (xvel > 0); 102512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } else { 102612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell newState = getTargetCheckedState(); 102712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 102812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } else { 1029d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette newState = oldState; 1030d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette } 1031d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette 1032d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette if (newState != oldState) { 1033d4e7790fee10e21b41a1c387c2734722bda56a0bAlan Viverette playSoundEffect(SoundEffectConstants.CLICK); 103412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 103503306a0b275c24e9c4681bee53e5dd98c0654e01Alan Viverette // Always call setChecked so that the thumb is moved back to the correct edge 103603306a0b275c24e9c4681bee53e5dd98c0654e01Alan Viverette setChecked(newState); 103786453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette cancelSuperTouch(ev); 103812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 103912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 104012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private void animateThumbToCheckedState(boolean newCheckedState) { 1041cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette final float targetPosition = newCheckedState ? 1 : 0; 1042cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette mPositionAnimator = ObjectAnimator.ofFloat(this, THUMB_POS, targetPosition); 1043cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette mPositionAnimator.setDuration(THUMB_ANIMATION_DURATION); 1044cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette mPositionAnimator.setAutoCancel(true); 1045cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette mPositionAnimator.start(); 104612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 104712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 1048cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette private void cancelPositionAnimator() { 1049cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette if (mPositionAnimator != null) { 1050cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette mPositionAnimator.cancel(); 105128efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio } 105228efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio } 105328efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio 1054cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette private boolean getTargetCheckedState() { 1055cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette return mThumbPosition > 0.5f; 1056cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } 1057cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 1058cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette /** 1059cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette * Sets the thumb position as a decimal value between 0 (off) and 1 (on). 1060cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette * 1061cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette * @param position new position between [0,1] 1062cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette */ 1063cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette private void setThumbPosition(float position) { 1064cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette mThumbPosition = position; 1065cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette invalidate(); 1066cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } 1067cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 1068cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette @Override 1069cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette public void toggle() { 107086453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette setChecked(!isChecked()); 107112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 107212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 107312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 107412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setChecked(boolean checked) { 107512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.setChecked(checked); 1076cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 1077467d629ca714cd74658043c1ddfec36c60d898c1Alan Viverette // Calling the super method may result in setChecked() getting called 1078467d629ca714cd74658043c1ddfec36c60d898c1Alan Viverette // recursively with a different value, so load the REAL value... 1079467d629ca714cd74658043c1ddfec36c60d898c1Alan Viverette checked = isChecked(); 1080467d629ca714cd74658043c1ddfec36c60d898c1Alan Viverette 108186453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette if (isAttachedToWindow() && isLaidOut()) { 108286453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette animateThumbToCheckedState(checked); 108386453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette } else { 108486453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette // Immediately move the thumb to the new position. 108586453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette cancelPositionAnimator(); 108686453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette setThumbPosition(checked ? 1 : 0); 108786453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette } 108812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 108912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 109012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 109112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 109212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.onLayout(changed, left, top, right, bottom); 109312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 10940c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int opticalInsetLeft = 0; 10950c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int opticalInsetRight = 0; 10960c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (mThumbDrawable != null) { 10970c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final Rect trackPadding = mTempRect; 10980c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (mTrackDrawable != null) { 10990c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette mTrackDrawable.getPadding(trackPadding); 11000c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } else { 11010c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette trackPadding.setEmpty(); 11020c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 11030c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 11040c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final Insets insets = mThumbDrawable.getOpticalInsets(); 11050c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette opticalInsetLeft = Math.max(0, insets.left - trackPadding.left); 11060c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette opticalInsetRight = Math.max(0, insets.right - trackPadding.right); 11070c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 110828efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio 11090c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final int switchRight; 11100c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final int switchLeft; 111128efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio if (isLayoutRtl()) { 11120c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette switchLeft = getPaddingLeft() + opticalInsetLeft; 11130c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette switchRight = switchLeft + mSwitchWidth - opticalInsetLeft - opticalInsetRight; 111428efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio } else { 11150c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette switchRight = getWidth() - getPaddingRight() - opticalInsetRight; 11160c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette switchLeft = switchRight - mSwitchWidth + opticalInsetLeft + opticalInsetRight; 111728efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio } 1118c3eabb9b6ce7f556313c8e3870d76c5b443f1c51Joe Onorato 11190c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final int switchTop; 11200c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final int switchBottom; 112112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) { 112212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell default: 112312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case Gravity.TOP: 112412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchTop = getPaddingTop(); 112512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchBottom = switchTop + mSwitchHeight; 112612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 112712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 112812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case Gravity.CENTER_VERTICAL: 112912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchTop = (getPaddingTop() + getHeight() - getPaddingBottom()) / 2 - 113012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchHeight / 2; 113112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchBottom = switchTop + mSwitchHeight; 113212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 113312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 113412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case Gravity.BOTTOM: 113512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchBottom = getHeight() - getPaddingBottom(); 113612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchTop = switchBottom - mSwitchHeight; 113712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 113812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 113912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 114012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchLeft = switchLeft; 114112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchTop = switchTop; 114212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchBottom = switchBottom; 114312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchRight = switchRight; 114412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 114512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 114612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 1147ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette public void draw(Canvas c) { 11484d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final Rect padding = mTempRect; 11495876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette final int switchLeft = mSwitchLeft; 11505876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette final int switchTop = mSwitchTop; 11515876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette final int switchRight = mSwitchRight; 11525876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette final int switchBottom = mSwitchBottom; 11530c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 11540c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int thumbInitialLeft = switchLeft + getThumbOffset(); 11550c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 11560c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final Insets thumbInsets; 11570c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (mThumbDrawable != null) { 11580c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette thumbInsets = mThumbDrawable.getOpticalInsets(); 11590c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } else { 11600c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette thumbInsets = Insets.NONE; 11618bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette } 1162cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 11630c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette // Layout the track. 11640c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (mTrackDrawable != null) { 11650c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette mTrackDrawable.getPadding(padding); 11669b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette 11670c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette // Adjust thumb position for track padding. 11680c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette thumbInitialLeft += padding.left; 11690c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 11700c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette // If necessary, offset by the optical insets of the thumb asset. 11710c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int trackLeft = switchLeft; 11720c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int trackTop = switchTop; 11730c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int trackRight = switchRight; 11740c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette int trackBottom = switchBottom; 11750c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (thumbInsets != Insets.NONE) { 11760c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (thumbInsets.left > padding.left) { 11770c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette trackLeft += thumbInsets.left - padding.left; 11780c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 11790c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (thumbInsets.top > padding.top) { 11800c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette trackTop += thumbInsets.top - padding.top; 11810c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 11820c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (thumbInsets.right > padding.right) { 11830c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette trackRight -= thumbInsets.right - padding.right; 11840c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 11850c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (thumbInsets.bottom > padding.bottom) { 11860c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette trackBottom -= thumbInsets.bottom - padding.bottom; 11870c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 11880c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 11890c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette mTrackDrawable.setBounds(trackLeft, trackTop, trackRight, trackBottom); 11900c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 11919b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette 1192661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette // Layout the thumb. 11934d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (mThumbDrawable != null) { 11944d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette mThumbDrawable.getPadding(padding); 11950c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 11960c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final int thumbLeft = thumbInitialLeft - padding.left; 11970c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final int thumbRight = thumbInitialLeft + mThumbWidth + padding.right; 11984d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom); 11994d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 12004d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final Drawable background = getBackground(); 12014d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (background != null) { 12024d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette background.setHotspotBounds(thumbLeft, switchTop, thumbRight, switchBottom); 12034d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } 120461956606818918194a38e045a8e35e7108480e5eAlan Viverette } 120561956606818918194a38e045a8e35e7108480e5eAlan Viverette 1206ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette // Draw the background. 1207ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette super.draw(c); 1208ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette } 1209ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette 1210ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette @Override 1211ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette protected void onDraw(Canvas canvas) { 121261956606818918194a38e045a8e35e7108480e5eAlan Viverette super.onDraw(canvas); 121361956606818918194a38e045a8e35e7108480e5eAlan Viverette 12144d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final Rect padding = mTempRect; 1215ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette final Drawable trackDrawable = mTrackDrawable; 12164d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (trackDrawable != null) { 12174d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette trackDrawable.getPadding(padding); 12184d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } else { 12194d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette padding.setEmpty(); 12204d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } 1221ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette 1222ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette final int switchTop = mSwitchTop; 1223ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette final int switchBottom = mSwitchBottom; 12244d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final int switchInnerTop = switchTop + padding.top; 12254d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final int switchInnerBottom = switchBottom - padding.bottom; 12264d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 12274d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final Drawable thumbDrawable = mThumbDrawable; 12284d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (trackDrawable != null) { 12294d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (mSplitTrack && thumbDrawable != null) { 12304d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final Insets insets = thumbDrawable.getOpticalInsets(); 12314d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette thumbDrawable.copyBounds(padding); 12324d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette padding.left += insets.left; 12334d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette padding.right -= insets.right; 12344d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 12354d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final int saveCount = canvas.save(); 12364d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette canvas.clipRect(padding, Op.DIFFERENCE); 12374d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette trackDrawable.draw(canvas); 12384d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette canvas.restoreToCount(saveCount); 12394d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } else { 12404d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette trackDrawable.draw(canvas); 12414d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } 1242661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 124361956606818918194a38e045a8e35e7108480e5eAlan Viverette 124461956606818918194a38e045a8e35e7108480e5eAlan Viverette final int saveCount = canvas.save(); 12454d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 12464d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (thumbDrawable != null) { 12474d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette thumbDrawable.draw(canvas); 12484d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } 124912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 12505876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette final Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout; 1251be06e3292b295324b3b47d13f9a40787b666309fFabrice Di Meglio if (switchText != null) { 1252661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int drawableState[] = getDrawableState(); 1253661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette if (mTextColors != null) { 1254661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette mTextPaint.setColor(mTextColors.getColorForState(drawableState, 0)); 1255661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 1256661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette mTextPaint.drawableState = drawableState; 1257661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 12584d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final int cX; 12594d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (thumbDrawable != null) { 12604d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final Rect bounds = thumbDrawable.getBounds(); 12614d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette cX = bounds.left + bounds.right; 12624d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } else { 1263dec17299fef93f673d8e8cab0ec0f734bf6b8539Alan Viverette cX = getWidth(); 12644d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } 12654d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 12664d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette final int left = cX / 2 - switchText.getWidth() / 2; 12675876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette final int top = (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2; 12685876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette canvas.translate(left, top); 1269be06e3292b295324b3b47d13f9a40787b666309fFabrice Di Meglio switchText.draw(canvas); 1270be06e3292b295324b3b47d13f9a40787b666309fFabrice Di Meglio } 127112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 12725876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette canvas.restoreToCount(saveCount); 127312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 127412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 127512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 127628efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio public int getCompoundPaddingLeft() { 127728efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio if (!isLayoutRtl()) { 127828efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio return super.getCompoundPaddingLeft(); 127928efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio } 128028efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio int padding = super.getCompoundPaddingLeft() + mSwitchWidth; 128128efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio if (!TextUtils.isEmpty(getText())) { 128228efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio padding += mSwitchPadding; 128328efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio } 128428efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio return padding; 128528efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio } 128628efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio 128728efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio @Override 128812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public int getCompoundPaddingRight() { 128928efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio if (isLayoutRtl()) { 129028efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio return super.getCompoundPaddingRight(); 129128efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio } 129212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int padding = super.getCompoundPaddingRight() + mSwitchWidth; 129312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (!TextUtils.isEmpty(getText())) { 129412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell padding += mSwitchPadding; 129512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 129612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return padding; 129712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 129812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 1299cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette /** 1300cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette * Translates thumb position to offset according to current RTL setting and 13010c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette * thumb scroll range. Accounts for both track and thumb padding. 1302cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette * 1303cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette * @return thumb offset 1304cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette */ 1305cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette private int getThumbOffset() { 1306cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette final float thumbPosition; 1307cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette if (isLayoutRtl()) { 1308cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette thumbPosition = 1 - mThumbPosition; 1309cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } else { 1310cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette thumbPosition = mThumbPosition; 1311cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } 1312cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette return (int) (thumbPosition * getThumbScrollRange() + 0.5f); 1313cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } 1314cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 131512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int getThumbScrollRange() { 13164d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (mTrackDrawable != null) { 13170c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final Rect padding = mTempRect; 13180c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette mTrackDrawable.getPadding(padding); 13190c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 13200c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette final Insets insets; 13210c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette if (mThumbDrawable != null) { 13220c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette insets = mThumbDrawable.getOpticalInsets(); 13230c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } else { 13240c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette insets = Insets.NONE; 13250c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette } 13260c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette 13270c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette return mSwitchWidth - mThumbWidth - padding.left - padding.right 13280c0dde7171c7ea35bbc6d64a41f94b428cb4d1f6Alan Viverette - insets.left - insets.right; 13294d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } else { 133012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return 0; 133112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 133212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 133312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 133412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 133512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell protected int[] onCreateDrawableState(int extraSpace) { 133612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); 133712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (isChecked()) { 133812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mergeDrawableStates(drawableState, CHECKED_STATE_SET); 133912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 134012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return drawableState; 134112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 134212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 134312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 134412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell protected void drawableStateChanged() { 134512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.drawableStateChanged(); 134612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 1347ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette final int[] state = getDrawableState(); 1348ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette boolean changed = false; 1349661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 1350ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette final Drawable thumbDrawable = mThumbDrawable; 1351ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette if (thumbDrawable != null && thumbDrawable.isStateful()) { 1352ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette changed |= thumbDrawable.setState(state); 1353661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 135412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 1355ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette final Drawable trackDrawable = mTrackDrawable; 1356ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette if (trackDrawable != null && trackDrawable.isStateful()) { 1357ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette changed |= trackDrawable.setState(state); 1358661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 135912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 1360ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette if (changed) { 1361ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette invalidate(); 1362ad0020f8075ecf768cb610d60dbb167d41f0fbe5Alan Viverette } 136312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 136412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 1365cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette @Override 13668de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette public void drawableHotspotChanged(float x, float y) { 13678de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette super.drawableHotspotChanged(x, y); 1368cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette 1369cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette if (mThumbDrawable != null) { 1370cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette mThumbDrawable.setHotspot(x, y); 1371cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette } 1372cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette 1373cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette if (mTrackDrawable != null) { 1374cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette mTrackDrawable.setHotspot(x, y); 1375cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette } 1376cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette } 1377cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette 137812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 1379f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette protected boolean verifyDrawable(@NonNull Drawable who) { 138012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable; 138112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 138212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 138312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 138412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void jumpDrawablesToCurrentState() { 138512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.jumpDrawablesToCurrentState(); 13864d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 13874d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (mThumbDrawable != null) { 13884d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette mThumbDrawable.jumpToCurrentState(); 13894d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } 13904d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 13914d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette if (mTrackDrawable != null) { 13924d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette mTrackDrawable.jumpToCurrentState(); 13934d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } 13944d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette 1395ee20d7799f25eba9881344473190077bf1d5a4c4Alan Viverette if (mPositionAnimator != null && mPositionAnimator.isStarted()) { 13964d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette mPositionAnimator.end(); 13974d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette mPositionAnimator = null; 13984d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette } 139912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 14008a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 14018a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 1402a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn public CharSequence getAccessibilityClassName() { 1403a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn return Switch.class.getName(); 1404a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn } 1405a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn 1406a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn @Override 14076d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme public void onProvideStructure(ViewStructure structure) { 14086d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme super.onProvideStructure(structure); 1409640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme onProvideAutoFillStructureForAssistOrAutofill(structure); 14106d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 14116d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 14126d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 1413640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme public void onProvideAutofillStructure(ViewStructure structure, int flags) { 1414640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme super.onProvideAutofillStructure(structure, flags); 1415640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme onProvideAutoFillStructureForAssistOrAutofill(structure); 14166d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 14171ca634a544a47193dd9e57f9b3eb3e42ab0dbbf1Felipe Leme 14186d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme // NOTE: currently there is no difference for Assist or AutoFill, so it doesn't take flags 1419640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme private void onProvideAutoFillStructureForAssistOrAutofill(ViewStructure structure) { 1420a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn CharSequence switchText = isChecked() ? mTextOn : mTextOff; 1421a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn if (!TextUtils.isEmpty(switchText)) { 1422a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9dDianne Hackborn CharSequence oldText = structure.getText(); 1423a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn if (TextUtils.isEmpty(oldText)) { 1424a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9dDianne Hackborn structure.setText(switchText); 1425a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn } else { 1426a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn StringBuilder newText = new StringBuilder(); 1427a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn newText.append(oldText).append(' ').append(switchText); 1428a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9dDianne Hackborn structure.setText(newText); 1429a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn } 14305cfaae4aae744574f0fcc0876cdc5473bc1a344dJames Cook // The style of the label text is provided via the base TextView class. This is more 14315cfaae4aae744574f0fcc0876cdc5473bc1a344dJames Cook // relevant than the style of the (optional) on/off text on the switch button itself, 14325cfaae4aae744574f0fcc0876cdc5473bc1a344dJames Cook // so ignore the size/color/style stored this.mTextPaint. 1433a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn } 14348a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 14358a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 1436a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 14378a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 1438a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 1439a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onInitializeAccessibilityNodeInfoInternal(info); 144078bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov CharSequence switchText = isChecked() ? mTextOn : mTextOff; 144178bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov if (!TextUtils.isEmpty(switchText)) { 144278bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov CharSequence oldText = info.getText(); 144378bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov if (TextUtils.isEmpty(oldText)) { 144478bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov info.setText(switchText); 144578bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov } else { 144678bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov StringBuilder newText = new StringBuilder(); 144778bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov newText.append(oldText).append(' ').append(switchText); 144878bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov info.setText(newText); 144978bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov } 145078bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov } 14518a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 1452cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 1453cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette private static final FloatProperty<Switch> THUMB_POS = new FloatProperty<Switch>("thumbPos") { 1454cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette @Override 1455cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette public Float get(Switch object) { 1456cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette return object.mThumbPosition; 1457cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } 1458cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette 1459cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette @Override 1460cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette public void setValue(Switch object, float value) { 1461cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette object.setThumbPosition(value); 1462cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette } 1463cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette }; 146412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell} 1465