Switch.java revision 9b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0
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;
2012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.Context;
2112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.ColorStateList;
2212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.Resources;
2312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.TypedArray;
2412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Canvas;
25661e63658da39cccfe49a129e4860455716ff3c9Alan Viveretteimport android.graphics.Insets;
2612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Paint;
2712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Rect;
2812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Typeface;
29661e63658da39cccfe49a129e4860455716ff3c9Alan Viveretteimport android.graphics.Region.Op;
3012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.drawable.Drawable;
3112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.Layout;
3212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.StaticLayout;
3312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.TextPaint;
3412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.TextUtils;
354c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandlerimport android.text.method.AllCapsTransformationMethod;
364c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandlerimport android.text.method.TransformationMethod2;
3712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.util.AttributeSet;
38cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viveretteimport android.util.FloatProperty;
39cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viveretteimport android.util.MathUtils;
4012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.Gravity;
4112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.MotionEvent;
4212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.VelocityTracker;
4312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.ViewConfiguration;
4463bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent;
458a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo;
4612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
47be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powellimport com.android.internal.R;
48be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powell
4912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell/**
5012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * A Switch is a two-state toggle switch widget that can select between two
5112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * options. The user may drag the "thumb" back and forth to choose the selected option,
52150176d83023e3c486dba10edebb72af36b4099aChet Haase * or simply tap to toggle as if it were a checkbox. The {@link #setText(CharSequence) text}
53150176d83023e3c486dba10edebb72af36b4099aChet Haase * property controls the text displayed in the label for the switch, whereas the
54150176d83023e3c486dba10edebb72af36b4099aChet Haase * {@link #setTextOff(CharSequence) off} and {@link #setTextOn(CharSequence) on} text
55150176d83023e3c486dba10edebb72af36b4099aChet Haase * controls the text on the thumb. Similarly, the
56150176d83023e3c486dba10edebb72af36b4099aChet Haase * {@link #setTextAppearance(android.content.Context, int) textAppearance} and the related
57150176d83023e3c486dba10edebb72af36b4099aChet Haase * setTypeface() methods control the typeface and style of label text, whereas the
58150176d83023e3c486dba10edebb72af36b4099aChet Haase * {@link #setSwitchTextAppearance(android.content.Context, int) switchTextAppearance} and
59150176d83023e3c486dba10edebb72af36b4099aChet Haase * the related seSwitchTypeface() methods control that of the thumb.
6012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell *
614c359b76f9a030f92a302ba74a528faa170bad4eScott Main * <p>See the <a href="{@docRoot}guide/topics/ui/controls/togglebutton.html">Toggle Buttons</a>
624c359b76f9a030f92a302ba74a528faa170bad4eScott Main * guide.</p>
634c359b76f9a030f92a302ba74a528faa170bad4eScott Main *
644c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_textOn
654c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_textOff
664c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_switchMinWidth
674c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_switchPadding
684c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_switchTextAppearance
694c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_thumb
704c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_thumbTextPadding
714c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Switch_track
7212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */
7312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellpublic class Switch extends CompoundButton {
74cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    private static final int THUMB_ANIMATION_DURATION = 250;
75cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
7612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private static final int TOUCH_MODE_IDLE = 0;
7712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private static final int TOUCH_MODE_DOWN = 1;
7812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private static final int TOUCH_MODE_DRAGGING = 2;
7912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
8012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    // Enum for the "typeface" XML parameter.
8112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private static final int SANS = 1;
8212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private static final int SERIF = 2;
8312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private static final int MONOSPACE = 3;
8412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
8512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private Drawable mThumbDrawable;
8612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private Drawable mTrackDrawable;
8712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mThumbTextPadding;
8812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mSwitchMinWidth;
8912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mSwitchPadding;
90661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette    private boolean mSplitTrack;
9112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private CharSequence mTextOn;
9212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private CharSequence mTextOff;
932a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette    private boolean mShowText;
9412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
9512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mTouchMode;
9612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mTouchSlop;
9712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private float mTouchX;
9812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private float mTouchY;
9912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private VelocityTracker mVelocityTracker = VelocityTracker.obtain();
10012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mMinFlingVelocity;
10112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
10212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private float mThumbPosition;
10312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mSwitchWidth;
10412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mSwitchHeight;
1059b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette    private int mThumbWidth; // Does not include padding
10612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
10712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mSwitchLeft;
10812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mSwitchTop;
10912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mSwitchRight;
11012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int mSwitchBottom;
11112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
11212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private TextPaint mTextPaint;
11312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private ColorStateList mTextColors;
11412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private Layout mOnLayout;
11512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private Layout mOffLayout;
1164c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler    private TransformationMethod2 mSwitchTransformationMethod;
117cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    private ObjectAnimator mPositionAnimator;
11812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
119be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powell    @SuppressWarnings("hiding")
12012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private final Rect mTempRect = new Rect();
12112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
12212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private static final int[] CHECKED_STATE_SET = {
12312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        R.attr.state_checked
12412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    };
12512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
12612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
12712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * Construct a new Switch with default styling.
12812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     *
12912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @param context The Context that will determine this widget's theming.
13012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
13112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public Switch(Context context) {
13212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        this(context, null);
13312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
13412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
13512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
13612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * Construct a new Switch with default styling, overriding specific style
13712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * attributes as requested.
13812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     *
13912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @param context The Context that will determine this widget's theming.
14012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @param attrs Specification of attributes that should deviate from default styling.
14112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
14212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public Switch(Context context, AttributeSet attrs) {
14312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        this(context, attrs, com.android.internal.R.attr.switchStyle);
14412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
14512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
14612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
14712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * Construct a new Switch with a default style determined by the given theme attribute,
14812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * overriding specific style attributes as requested.
14912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     *
15012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @param context The Context that will determine this widget's theming.
15112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @param attrs Specification of attributes that should deviate from the default styling.
152617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * @param defStyleAttr An attribute in the current theme that contains a
153617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        reference to a style resource that supplies default values for
154617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        the view. Can be 0 to not look for defaults.
15512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
156617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public Switch(Context context, AttributeSet attrs, int defStyleAttr) {
157617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        this(context, attrs, defStyleAttr, 0);
158617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    }
159617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette
160617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette
161617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    /**
162617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * Construct a new Switch with a default style determined by the given theme
163617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * attribute or style resource, overriding specific style attributes as
164617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * requested.
165617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *
166617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * @param context The Context that will determine this widget's theming.
167617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * @param attrs Specification of attributes that should deviate from the
168617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        default styling.
169617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * @param defStyleAttr An attribute in the current theme that contains a
170617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        reference to a style resource that supplies default values for
171617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        the view. Can be 0 to not look for defaults.
172617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * @param defStyleRes A resource identifier of a style resource that
173617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        supplies default values for the view, used only if
174617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
175617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        to not look for defaults.
176617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     */
177617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public Switch(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
178617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        super(context, attrs, defStyleAttr, defStyleRes);
17912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
18012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
181661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette
182661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        final Resources res = getResources();
18312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTextPaint.density = res.getDisplayMetrics().density;
18412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTextPaint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
18512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
186617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        final TypedArray a = context.obtainStyledAttributes(
187617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette                attrs, com.android.internal.R.styleable.Switch, defStyleAttr, defStyleRes);
188150176d83023e3c486dba10edebb72af36b4099aChet Haase        mThumbDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_thumb);
189150176d83023e3c486dba10edebb72af36b4099aChet Haase        mTrackDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_track);
19012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTextOn = a.getText(com.android.internal.R.styleable.Switch_textOn);
19112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTextOff = a.getText(com.android.internal.R.styleable.Switch_textOff);
1922a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette        mShowText = a.getBoolean(com.android.internal.R.styleable.Switch_showText, true);
19312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mThumbTextPadding = a.getDimensionPixelSize(
19412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                com.android.internal.R.styleable.Switch_thumbTextPadding, 0);
19512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mSwitchMinWidth = a.getDimensionPixelSize(
19612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                com.android.internal.R.styleable.Switch_switchMinWidth, 0);
19712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mSwitchPadding = a.getDimensionPixelSize(
19812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                com.android.internal.R.styleable.Switch_switchPadding, 0);
199661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        mSplitTrack = a.getBoolean(com.android.internal.R.styleable.Switch_splitTrack, false);
20012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
201661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        final int appearance = a.getResourceId(
20212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                com.android.internal.R.styleable.Switch_switchTextAppearance, 0);
20312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (appearance != 0) {
204150176d83023e3c486dba10edebb72af36b4099aChet Haase            setSwitchTextAppearance(context, appearance);
20512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
20612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        a.recycle();
20712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
208661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        final ViewConfiguration config = ViewConfiguration.get(context);
20912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTouchSlop = config.getScaledTouchSlop();
21012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mMinFlingVelocity = config.getScaledMinimumFlingVelocity();
21112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
21212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        // Refresh display with current params
213e724ee4b04d121556e9764f72f9b921a0e16392aGilles Debunne        refreshDrawableState();
21412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        setChecked(isChecked());
21512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
21612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
21712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
21812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * Sets the switch text color, size, style, hint color, and highlight color
21912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * from the specified TextAppearance resource.
2206c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
2216c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_switchTextAppearance
22212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
223150176d83023e3c486dba10edebb72af36b4099aChet Haase    public void setSwitchTextAppearance(Context context, int resid) {
22412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        TypedArray appearance =
225150176d83023e3c486dba10edebb72af36b4099aChet Haase                context.obtainStyledAttributes(resid,
22612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        com.android.internal.R.styleable.TextAppearance);
22712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
22812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        ColorStateList colors;
22912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        int ts;
23012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
23112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        colors = appearance.getColorStateList(com.android.internal.R.styleable.
23212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                TextAppearance_textColor);
23312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (colors != null) {
23412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            mTextColors = colors;
235150176d83023e3c486dba10edebb72af36b4099aChet Haase        } else {
236150176d83023e3c486dba10edebb72af36b4099aChet Haase            // If no color set in TextAppearance, default to the view's textColor
237150176d83023e3c486dba10edebb72af36b4099aChet Haase            mTextColors = getTextColors();
23812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
23912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
24012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        ts = appearance.getDimensionPixelSize(com.android.internal.R.styleable.
24112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                TextAppearance_textSize, 0);
24212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (ts != 0) {
24312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            if (ts != mTextPaint.getTextSize()) {
24412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                mTextPaint.setTextSize(ts);
24512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                requestLayout();
24612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            }
24712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
24812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
24912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        int typefaceIndex, styleIndex;
25012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
25112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        typefaceIndex = appearance.getInt(com.android.internal.R.styleable.
25212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                TextAppearance_typeface, -1);
25312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        styleIndex = appearance.getInt(com.android.internal.R.styleable.
25412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                TextAppearance_textStyle, -1);
25512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
25612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        setSwitchTypefaceByIndex(typefaceIndex, styleIndex);
25712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
2584c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler        boolean allCaps = appearance.getBoolean(com.android.internal.R.styleable.
2594c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler                TextAppearance_textAllCaps, false);
2604c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler        if (allCaps) {
2614c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler            mSwitchTransformationMethod = new AllCapsTransformationMethod(getContext());
2624c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler            mSwitchTransformationMethod.setLengthChangesAllowed(true);
2634c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler        } else {
2644c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler            mSwitchTransformationMethod = null;
2654c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler        }
2664c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler
26712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        appearance.recycle();
26812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
26912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
27012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private void setSwitchTypefaceByIndex(int typefaceIndex, int styleIndex) {
27112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        Typeface tf = null;
27212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        switch (typefaceIndex) {
27312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case SANS:
27412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                tf = Typeface.SANS_SERIF;
27512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
27612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
27712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case SERIF:
27812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                tf = Typeface.SERIF;
27912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
28012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
28112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case MONOSPACE:
28212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                tf = Typeface.MONOSPACE;
28312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
28412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
28512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
28612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        setSwitchTypeface(tf, styleIndex);
28712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
28812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
28912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
29012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * Sets the typeface and style in which the text should be displayed on the
29112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * switch, and turns on the fake bold and italic bits in the Paint if the
29212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * Typeface that you provided does not have all the bits in the
29312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * style that you specified.
29412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
29512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public void setSwitchTypeface(Typeface tf, int style) {
29612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (style > 0) {
29712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            if (tf == null) {
29812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                tf = Typeface.defaultFromStyle(style);
29912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            } else {
30012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                tf = Typeface.create(tf, style);
30112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            }
30212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
30312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            setSwitchTypeface(tf);
30412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            // now compute what (if any) algorithmic styling is needed
30512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            int typefaceStyle = tf != null ? tf.getStyle() : 0;
30612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            int need = style & ~typefaceStyle;
30712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0);
30812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
30912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        } else {
310aa0980afab57a6aebb06e70f60e92511708fa5afVictoria Lease            mTextPaint.setFakeBoldText(false);
31112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            mTextPaint.setTextSkewX(0);
31212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            setSwitchTypeface(tf);
31312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
31412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
31512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
31612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
317150176d83023e3c486dba10edebb72af36b4099aChet Haase     * Sets the typeface in which the text should be displayed on the switch.
31812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * Note that not all Typeface families actually have bold and italic
31912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * variants, so you may need to use
32012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * {@link #setSwitchTypeface(Typeface, int)} to get the appearance
32112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * that you actually want.
32212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     *
32312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @attr ref android.R.styleable#TextView_typeface
32412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @attr ref android.R.styleable#TextView_textStyle
32512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
32612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public void setSwitchTypeface(Typeface tf) {
32712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (mTextPaint.getTypeface() != tf) {
32812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            mTextPaint.setTypeface(tf);
32912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
33012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            requestLayout();
33112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            invalidate();
33212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
33312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
33412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
33512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
3366c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Set the amount of horizontal padding between the switch and the associated text.
3376c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3386c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @param pixels Amount of padding in pixels
3396c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3406c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_switchPadding
3416c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
3426c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public void setSwitchPadding(int pixels) {
3436c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        mSwitchPadding = pixels;
3446c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        requestLayout();
3456c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
3466c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
3476c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
3486c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Get the amount of horizontal padding between the switch and the associated text.
3496c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3506c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @return Amount of padding in pixels
3516c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3526c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_switchPadding
3536c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
3546c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public int getSwitchPadding() {
3556c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        return mSwitchPadding;
3566c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
3576c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
3586c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
3596c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Set the minimum width of the switch in pixels. The switch's width will be the maximum
3606c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * of this value and its measured width as determined by the switch drawables and text used.
3616c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3626c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @param pixels Minimum width of the switch in pixels
3636c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3646c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_switchMinWidth
3656c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
3666c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public void setSwitchMinWidth(int pixels) {
3676c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        mSwitchMinWidth = pixels;
3686c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        requestLayout();
3696c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
3706c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
3716c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
3726c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Get the minimum width of the switch in pixels. The switch's width will be the maximum
3736c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * of this value and its measured width as determined by the switch drawables and text used.
3746c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3756c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @return Minimum width of the switch in pixels
3766c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3776c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_switchMinWidth
3786c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
3796c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public int getSwitchMinWidth() {
3806c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        return mSwitchMinWidth;
3816c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
3826c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
3836c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
3846c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Set the horizontal padding around the text drawn on the switch itself.
3856c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3866c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @param pixels Horizontal padding for switch thumb text in pixels
3876c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3886c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_thumbTextPadding
3896c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
3906c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public void setThumbTextPadding(int pixels) {
3916c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        mThumbTextPadding = pixels;
3926c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        requestLayout();
3936c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
3946c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
3956c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
3966c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Get the horizontal padding around the text drawn on the switch itself.
3976c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
3986c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @return Horizontal padding for switch thumb text in pixels
3996c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4006c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_thumbTextPadding
4016c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
4026c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public int getThumbTextPadding() {
4036c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        return mThumbTextPadding;
4046c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
4056c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
4066c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
4076c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Set the drawable used for the track that the switch slides within.
4086c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4096c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @param track Track drawable
4106c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4116c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_track
4126c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
4136c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public void setTrackDrawable(Drawable track) {
4146c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        mTrackDrawable = track;
4156c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        requestLayout();
4166c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
4176c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
4186c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
419d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Set the drawable used for the track that the switch slides within.
420d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
421dca510e026e3e75759bac84c3860dc84b83a608fAdam Powell     * @param resId Resource ID of a track drawable
422d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
423d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Switch_track
424d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
425d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public void setTrackResource(int resId) {
4268eea3ea5591e59f55cbb4f6b2b7e9363a285ced3Alan Viverette        setTrackDrawable(getContext().getDrawable(resId));
427d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
428d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
429d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
4306c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Get the drawable used for the track that the switch slides within.
4316c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4326c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @return Track drawable
4336c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4346c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_track
4356c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
4366c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public Drawable getTrackDrawable() {
4376c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        return mTrackDrawable;
4386c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
4396c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
4406c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
4416c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Set the drawable used for the switch "thumb" - the piece that the user
4426c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * can physically touch and drag along the track.
4436c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4446c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @param thumb Thumb drawable
4456c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4466c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_thumb
4476c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
4486c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public void setThumbDrawable(Drawable thumb) {
4496c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        mThumbDrawable = thumb;
4506c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        requestLayout();
4516c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
4526c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
4536c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
454d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Set the drawable used for the switch "thumb" - the piece that the user
455d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * can physically touch and drag along the track.
456d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
457dca510e026e3e75759bac84c3860dc84b83a608fAdam Powell     * @param resId Resource ID of a thumb drawable
458d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
459d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Switch_thumb
460d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
461d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public void setThumbResource(int resId) {
4628eea3ea5591e59f55cbb4f6b2b7e9363a285ced3Alan Viverette        setThumbDrawable(getContext().getDrawable(resId));
463d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
464d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
465d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
4666c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * Get the drawable used for the switch "thumb" - the piece that the user
4676c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * can physically touch and drag along the track.
4686c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4696c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @return Thumb drawable
4706c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
4716c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_thumb
4726c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     */
4736c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    public Drawable getThumbDrawable() {
4746c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell        return mThumbDrawable;
4756c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    }
4766c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell
4776c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell    /**
478661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     * Specifies whether the track should be split by the thumb. When true,
479661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     * the thumb's optical bounds will be clipped out of the track drawable,
480661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     * then the thumb will be drawn into the resulting gap.
481661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     *
482661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     * @param splitTrack Whether the track should be split by the thumb
483661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     *
484661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     * @attr ref android.R.styleable#Switch_splitTrack
485661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     */
486661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette    public void setSplitTrack(boolean splitTrack) {
487661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        mSplitTrack = splitTrack;
488661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        invalidate();
489661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette    }
490661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette
491661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette    /**
492661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     * Returns whether the track should be split by the thumb.
493661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     *
494661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     * @attr ref android.R.styleable#Switch_splitTrack
495661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette     */
496661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette    public boolean getSplitTrack() {
497661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        return mSplitTrack;
498661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette    }
499661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette
500661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette    /**
501150176d83023e3c486dba10edebb72af36b4099aChet Haase     * Returns the text displayed when the button is in the checked state.
5026c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
5036c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_textOn
50412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
50512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public CharSequence getTextOn() {
50612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        return mTextOn;
50712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
50812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
50912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
510150176d83023e3c486dba10edebb72af36b4099aChet Haase     * Sets the text displayed when the button is in the checked state.
5116c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
5126c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_textOn
51312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
51412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public void setTextOn(CharSequence textOn) {
51512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTextOn = textOn;
51612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        requestLayout();
51712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
51812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
51912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
520150176d83023e3c486dba10edebb72af36b4099aChet Haase     * Returns the text displayed when the button is not in the checked state.
5216c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
5226c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_textOff
52312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
52412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public CharSequence getTextOff() {
52512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        return mTextOff;
52612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
52712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
52812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
529150176d83023e3c486dba10edebb72af36b4099aChet Haase     * Sets the text displayed when the button is not in the checked state.
5306c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     *
5316c86e1ba41b56ccb3668dbb044fa348cd4b47d55Adam Powell     * @attr ref android.R.styleable#Switch_textOff
53212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
53312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public void setTextOff(CharSequence textOff) {
53412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTextOff = textOff;
53512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        requestLayout();
53612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
53712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
5382a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette    /**
5392a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette     * Sets whether the on/off text should be displayed.
5402a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette     *
5412a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette     * @param showText {@code true} to display on/off text
5429b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette     * @hide
5432a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette     */
5442a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette    public void setShowText(boolean showText) {
5452a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette        if (mShowText != showText) {
5462a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette            mShowText = showText;
5472a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette            requestLayout();
5482a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette        }
5492a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette    }
5502a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette
5512a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette    /**
5522a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette     * @return whether the on/off text should be displayed
5539b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette     * @hide
5542a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette     */
5552a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette    public boolean getShowText() {
5562a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette        return mShowText;
5572a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette    }
5582a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette
55912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
56012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5612a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette        if (mShowText) {
5622a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette            if (mOnLayout == null) {
5632a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette                mOnLayout = makeLayout(mTextOn);
5642a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette            }
5655876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette
5662a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette            if (mOffLayout == null) {
5672a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette                mOffLayout = makeLayout(mTextOff);
5682a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette            }
56912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
57012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
5718bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette        final int trackHeight;
5729b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        final Rect padding = mTempRect;
5738bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette        if (mTrackDrawable != null) {
5748bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette            mTrackDrawable.getPadding(padding);
5758bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette            trackHeight = mTrackDrawable.getIntrinsicHeight();
5768bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette        } else {
5778bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette            padding.setEmpty();
5788bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette            trackHeight = 0;
5798bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette        }
5808bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette
5819b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        final int thumbWidth;
5829b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        final int thumbHeight;
5838bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette        if (mThumbDrawable != null) {
5849b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            thumbWidth = mThumbDrawable.getIntrinsicWidth();
5859b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            thumbHeight = mThumbDrawable.getIntrinsicHeight();
5869b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        } else {
5879b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            thumbWidth = 0;
5889b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            thumbHeight = 0;
5898bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette        }
5908bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette
5919b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        final int maxTextWidth = mShowText ? Math.max(mOnLayout.getWidth(), mOffLayout.getWidth())
5929b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette                + mThumbTextPadding * 2 : 0;
5939b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        mThumbWidth = Math.max(maxTextWidth, thumbWidth);
5949b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette
59512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        final int switchWidth = Math.max(mSwitchMinWidth,
5969b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette                2 * mThumbWidth + padding.left + padding.right);
5974d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        final int switchHeight = Math.max(trackHeight, thumbHeight);
59812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mSwitchWidth = switchWidth;
59912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mSwitchHeight = switchHeight;
60012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
60112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
6024d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
60312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        final int measuredHeight = getMeasuredHeight();
60412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (measuredHeight < switchHeight) {
605189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn            setMeasuredDimension(getMeasuredWidthAndState(), switchHeight);
60612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
60712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
60812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
60963bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov    @Override
61063bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
61163bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov        super.onPopulateAccessibilityEvent(event);
6122a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette
6132a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette        final CharSequence text = isChecked() ? mTextOn : mTextOff;
6142a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette        if (text != null) {
6152a37cf8d763750853e2b4e036bc7cb4486c78e1dAlan Viverette            event.getText().add(text);
6167650259a597dd24137420d32acc35efc44db381eSvetoslav Ganov        }
61763bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov    }
61863bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov
61912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private Layout makeLayout(CharSequence text) {
6204c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler        final CharSequence transformed = (mSwitchTransformationMethod != null)
6214c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler                    ? mSwitchTransformationMethod.getTransformation(text, this)
6224c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler                    : text;
6234c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler
6244c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler        return new StaticLayout(transformed, mTextPaint,
6254c3308de7d51b16b1450c21787b442d84ace3984Daniel Sandler                (int) Math.ceil(Layout.getDesiredWidth(transformed, mTextPaint)),
62612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
62712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
62812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
62912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
63012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @return true if (x, y) is within the target area of the switch thumb
63112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
63212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private boolean hitThumb(float x, float y) {
633cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        // Relies on mTempRect, MUST be called first!
634cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        final int thumbOffset = getThumbOffset();
635cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
63612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mThumbDrawable.getPadding(mTempRect);
63712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        final int thumbTop = mSwitchTop - mTouchSlop;
638cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        final int thumbLeft = mSwitchLeft + thumbOffset - mTouchSlop;
63912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        final int thumbRight = thumbLeft + mThumbWidth +
64012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                mTempRect.left + mTempRect.right + mTouchSlop;
64112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        final int thumbBottom = mSwitchBottom + mTouchSlop;
64212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        return x > thumbLeft && x < thumbRight && y > thumbTop && y < thumbBottom;
64312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
64412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
64512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
64612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public boolean onTouchEvent(MotionEvent ev) {
64712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mVelocityTracker.addMovement(ev);
64812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        final int action = ev.getActionMasked();
64912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        switch (action) {
65012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case MotionEvent.ACTION_DOWN: {
65112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                final float x = ev.getX();
65212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                final float y = ev.getY();
653c2ab0d665c9d1c332fbd726abf582a27cf7a6701Gilles Debunne                if (isEnabled() && hitThumb(x, y)) {
65412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    mTouchMode = TOUCH_MODE_DOWN;
65512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    mTouchX = x;
65612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    mTouchY = y;
65712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                }
65812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
65912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            }
66012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
66112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case MotionEvent.ACTION_MOVE: {
66212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                switch (mTouchMode) {
66312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    case TOUCH_MODE_IDLE:
66412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        // Didn't target the thumb, treat normally.
66512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        break;
66612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
66712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    case TOUCH_MODE_DOWN: {
66812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        final float x = ev.getX();
66912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        final float y = ev.getY();
67012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        if (Math.abs(x - mTouchX) > mTouchSlop ||
67112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                                Math.abs(y - mTouchY) > mTouchSlop) {
67212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                            mTouchMode = TOUCH_MODE_DRAGGING;
67312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                            getParent().requestDisallowInterceptTouchEvent(true);
67412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                            mTouchX = x;
67512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                            mTouchY = y;
67612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                            return true;
67712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        }
67812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        break;
67912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    }
68012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
68112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    case TOUCH_MODE_DRAGGING: {
68212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        final float x = ev.getX();
683cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        final int thumbScrollRange = getThumbScrollRange();
684cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        final float thumbScrollOffset = x - mTouchX;
685cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        float dPos;
686cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        if (thumbScrollRange != 0) {
687cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                            dPos = thumbScrollOffset / thumbScrollRange;
688cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        } else {
689cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                            // If the thumb scroll range is empty, just use the
690cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                            // movement direction to snap on or off.
691cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                            dPos = thumbScrollOffset > 0 ? 1 : -1;
692cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        }
693cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        if (isLayoutRtl()) {
694cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                            dPos = -dPos;
695cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        }
696cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                        final float newPos = MathUtils.constrain(mThumbPosition + dPos, 0, 1);
69712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        if (newPos != mThumbPosition) {
69812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                            mTouchX = x;
699cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette                            setThumbPosition(newPos);
70012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        }
70112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        return true;
70212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    }
70312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                }
70412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
70512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            }
70612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
70712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case MotionEvent.ACTION_UP:
70812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case MotionEvent.ACTION_CANCEL: {
70912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                if (mTouchMode == TOUCH_MODE_DRAGGING) {
71012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    stopDrag(ev);
711ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette                    // Allow super class to handle pressed state, etc.
712ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette                    super.onTouchEvent(ev);
71312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                    return true;
71412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                }
71512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                mTouchMode = TOUCH_MODE_IDLE;
71612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                mVelocityTracker.clear();
71712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
71812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            }
71912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
72012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
72112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        return super.onTouchEvent(ev);
72212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
72312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
72412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private void cancelSuperTouch(MotionEvent ev) {
72512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        MotionEvent cancel = MotionEvent.obtain(ev);
72612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        cancel.setAction(MotionEvent.ACTION_CANCEL);
72712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        super.onTouchEvent(cancel);
72812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        cancel.recycle();
72912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
73012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
73112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    /**
73212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * Called from onTouchEvent to end a drag operation.
73312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     *
73412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     * @param ev Event that triggered the end of drag mode - ACTION_UP or ACTION_CANCEL
73512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell     */
73612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private void stopDrag(MotionEvent ev) {
73712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mTouchMode = TOUCH_MODE_IDLE;
73812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
73986453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        // Commit the change if the event is up and not canceled and the switch
74086453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        // has not been disabled during the drag.
74186453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        final boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP && isEnabled();
74286453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        final boolean newState;
74312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (commitChange) {
74412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            mVelocityTracker.computeCurrentVelocity(1000);
74586453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette            final float xvel = mVelocityTracker.getXVelocity();
74612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            if (Math.abs(xvel) > mMinFlingVelocity) {
74728efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio                newState = isLayoutRtl() ? (xvel < 0) : (xvel > 0);
74812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            } else {
74912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                newState = getTargetCheckedState();
75012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            }
75112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        } else {
75286453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette            newState = isChecked();
75312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
75486453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette
75586453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        setChecked(newState);
75686453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        cancelSuperTouch(ev);
75712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
75812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
75912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private void animateThumbToCheckedState(boolean newCheckedState) {
760cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        final float targetPosition = newCheckedState ? 1 : 0;
761cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        mPositionAnimator = ObjectAnimator.ofFloat(this, THUMB_POS, targetPosition);
762cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        mPositionAnimator.setDuration(THUMB_ANIMATION_DURATION);
763cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        mPositionAnimator.setAutoCancel(true);
764cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        mPositionAnimator.start();
76512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
76612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
767cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    private void cancelPositionAnimator() {
768cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        if (mPositionAnimator != null) {
769cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette            mPositionAnimator.cancel();
77028efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        }
77128efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio    }
77228efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio
773cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    private boolean getTargetCheckedState() {
774cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        return mThumbPosition > 0.5f;
775cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    }
776cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
777cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    /**
778cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette     * Sets the thumb position as a decimal value between 0 (off) and 1 (on).
779cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette     *
780cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette     * @param position new position between [0,1]
781cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette     */
782cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    private void setThumbPosition(float position) {
783cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        mThumbPosition = position;
784cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        invalidate();
785cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    }
786cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
787cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    @Override
788cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    public void toggle() {
78986453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        setChecked(!isChecked());
79012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
79112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
79212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
79312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public void setChecked(boolean checked) {
79412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        super.setChecked(checked);
795cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
79686453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        if (isAttachedToWindow() && isLaidOut()) {
79786453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette            animateThumbToCheckedState(checked);
79886453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        } else {
79986453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette            // Immediately move the thumb to the new position.
80086453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette            cancelPositionAnimator();
80186453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette            setThumbPosition(checked ? 1 : 0);
80286453ff147f28b0c16bea73da5b261feed50efb7Alan Viverette        }
80312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
80412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
80512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
80612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
80712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        super.onLayout(changed, left, top, right, bottom);
80812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
8099b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        int switchRight;
8109b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        int switchLeft;
81128efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio
81228efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        if (isLayoutRtl()) {
8139b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            switchLeft = getPaddingLeft();
8149b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            switchRight = switchLeft + mSwitchWidth;
81528efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        } else {
8169b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            switchRight = getWidth() - getPaddingRight();
8179b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            switchLeft = switchRight - mSwitchWidth;
81828efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        }
819c3eabb9b6ce7f556313c8e3870d76c5b443f1c51Joe Onorato
8209b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        int switchTop = 0;
8219b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        int switchBottom = 0;
82212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) {
82312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            default:
82412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case Gravity.TOP:
82512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                switchTop = getPaddingTop();
82612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                switchBottom = switchTop + mSwitchHeight;
82712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
82812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
82912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case Gravity.CENTER_VERTICAL:
83012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                switchTop = (getPaddingTop() + getHeight() - getPaddingBottom()) / 2 -
83112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                        mSwitchHeight / 2;
83212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                switchBottom = switchTop + mSwitchHeight;
83312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
83412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
83512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            case Gravity.BOTTOM:
83612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                switchBottom = getHeight() - getPaddingBottom();
83712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                switchTop = switchBottom - mSwitchHeight;
83812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell                break;
83912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
84012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
84112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mSwitchLeft = switchLeft;
84212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mSwitchTop = switchTop;
84312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mSwitchBottom = switchBottom;
84412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        mSwitchRight = switchRight;
84512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
84612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
84712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
848ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette    public void draw(Canvas c) {
8494d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        final Rect padding = mTempRect;
8509b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette
8519b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        // Layout the track.
8525876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette        final int switchLeft = mSwitchLeft;
8535876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette        final int switchTop = mSwitchTop;
8545876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette        final int switchRight = mSwitchRight;
8555876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette        final int switchBottom = mSwitchBottom;
8568bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette        if (mTrackDrawable != null) {
8579b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            mTrackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom);
8588bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette            mTrackDrawable.getPadding(padding);
8598bb399069da4e46b231333cff6880a0cf35b9417Alan Viverette        }
860cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
8619b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        final int switchInnerLeft = switchLeft + padding.left;
8629b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette
8639b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        // Relies on mTempRect, MUST be called first!
8649b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        final int thumbPos = getThumbOffset();
8659b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette
866661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        // Layout the thumb.
8674d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        if (mThumbDrawable != null) {
8684d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            mThumbDrawable.getPadding(padding);
8699b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            final int thumbLeft = switchInnerLeft - padding.left + thumbPos;
8709b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            final int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + padding.right;
8714d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);
8724d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
8734d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            final Drawable background = getBackground();
8744d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            if (background != null) {
8754d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                background.setHotspotBounds(thumbLeft, switchTop, thumbRight, switchBottom);
8764d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            }
87761956606818918194a38e045a8e35e7108480e5eAlan Viverette        }
87861956606818918194a38e045a8e35e7108480e5eAlan Viverette
879ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette        // Draw the background.
880ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette        super.draw(c);
881ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette    }
882ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette
883ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette    @Override
884ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette    protected void onDraw(Canvas canvas) {
88561956606818918194a38e045a8e35e7108480e5eAlan Viverette        super.onDraw(canvas);
88661956606818918194a38e045a8e35e7108480e5eAlan Viverette
8874d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        final Rect padding = mTempRect;
888ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette        final Drawable trackDrawable = mTrackDrawable;
8894d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        if (trackDrawable != null) {
8904d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            trackDrawable.getPadding(padding);
8914d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        } else {
8924d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            padding.setEmpty();
8934d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        }
894ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette
895ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette        final int switchTop = mSwitchTop;
896ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette        final int switchBottom = mSwitchBottom;
8979b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        final int switchInnerLeft = mSwitchLeft + padding.left;
8984d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        final int switchInnerTop = switchTop + padding.top;
8999b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette        final int switchInnerRight = mSwitchRight - padding.right;
9004d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        final int switchInnerBottom = switchBottom - padding.bottom;
9014d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
9024d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        final Drawable thumbDrawable = mThumbDrawable;
9034d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        if (trackDrawable != null) {
9044d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            if (mSplitTrack && thumbDrawable != null) {
9054d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                final Insets insets = thumbDrawable.getOpticalInsets();
9064d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                thumbDrawable.copyBounds(padding);
9074d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                padding.left += insets.left;
9084d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                padding.right -= insets.right;
9094d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
9104d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                final int saveCount = canvas.save();
9114d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                canvas.clipRect(padding, Op.DIFFERENCE);
9124d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                trackDrawable.draw(canvas);
9134d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                canvas.restoreToCount(saveCount);
9144d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            } else {
9154d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                trackDrawable.draw(canvas);
9164d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            }
917661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        }
91861956606818918194a38e045a8e35e7108480e5eAlan Viverette
91961956606818918194a38e045a8e35e7108480e5eAlan Viverette        final int saveCount = canvas.save();
9204d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
9214d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        if (thumbDrawable != null) {
9229b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
9234d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            thumbDrawable.draw(canvas);
9244d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        }
92512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
9265876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette        final Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
927be06e3292b295324b3b47d13f9a40787b666309fFabrice Di Meglio        if (switchText != null) {
928661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette            final int drawableState[] = getDrawableState();
929661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette            if (mTextColors != null) {
930661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette                mTextPaint.setColor(mTextColors.getColorForState(drawableState, 0));
931661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette            }
932661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette            mTextPaint.drawableState = drawableState;
933661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette
9344d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            final int cX;
9354d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            if (thumbDrawable != null) {
9364d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                final Rect bounds = thumbDrawable.getBounds();
9374d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette                cX = bounds.left + bounds.right;
9384d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            } else {
939dec17299fef93f673d8e8cab0ec0f734bf6b8539Alan Viverette                cX = getWidth();
9404d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            }
9414d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
9424d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            final int left = cX / 2 - switchText.getWidth() / 2;
9435876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette            final int top = (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2;
9445876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette            canvas.translate(left, top);
945be06e3292b295324b3b47d13f9a40787b666309fFabrice Di Meglio            switchText.draw(canvas);
946be06e3292b295324b3b47d13f9a40787b666309fFabrice Di Meglio        }
94712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
9485876ff4a0ac938297bfd114da6b5d8c9dcb4cef6Alan Viverette        canvas.restoreToCount(saveCount);
94912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
95012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
95112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
95228efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio    public int getCompoundPaddingLeft() {
95328efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        if (!isLayoutRtl()) {
95428efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio            return super.getCompoundPaddingLeft();
95528efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        }
95628efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        int padding = super.getCompoundPaddingLeft() + mSwitchWidth;
95728efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        if (!TextUtils.isEmpty(getText())) {
95828efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio            padding += mSwitchPadding;
95928efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        }
96028efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        return padding;
96128efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio    }
96228efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio
96328efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio    @Override
96412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public int getCompoundPaddingRight() {
96528efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        if (isLayoutRtl()) {
96628efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio            return super.getCompoundPaddingRight();
96728efba38c07c78f4a349d599b7ad3d7b517c5e97Fabrice Di Meglio        }
96812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        int padding = super.getCompoundPaddingRight() + mSwitchWidth;
96912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (!TextUtils.isEmpty(getText())) {
97012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            padding += mSwitchPadding;
97112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
97212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        return padding;
97312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
97412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
975cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    /**
976cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette     * Translates thumb position to offset according to current RTL setting and
9779b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette     * thumb scroll range.
978cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette     *
979cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette     * @return thumb offset
980cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette     */
981cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    private int getThumbOffset() {
982cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        final float thumbPosition;
983cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        if (isLayoutRtl()) {
984cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette            thumbPosition = 1 - mThumbPosition;
985cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        } else {
986cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette            thumbPosition = mThumbPosition;
987cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        }
988cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        return (int) (thumbPosition * getThumbScrollRange() + 0.5f);
989cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    }
990cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
99112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    private int getThumbScrollRange() {
9924d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        if (mTrackDrawable != null) {
9939b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            mTrackDrawable.getPadding(mTempRect);
9949b38f6c2cd1d97bb0d1a21e2f9545e02fae851e0Alan Viverette            return mSwitchWidth - mThumbWidth - mTempRect.left - mTempRect.right;
9954d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        } else {
99612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            return 0;
99712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
99812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
99912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
100012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
100112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    protected int[] onCreateDrawableState(int extraSpace) {
100212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
100312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        if (isChecked()) {
100412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
100512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        }
100612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        return drawableState;
100712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
100812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
100912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
101012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    protected void drawableStateChanged() {
101112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        super.drawableStateChanged();
101212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
1013661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        final int[] myDrawableState = getDrawableState();
1014661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette
10152356c5e69b0911e6334ebf6374217898371be5acAlan Viverette        if (mThumbDrawable != null) {
10162356c5e69b0911e6334ebf6374217898371be5acAlan Viverette            mThumbDrawable.setState(myDrawableState);
1017661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        }
101812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
1019661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        if (mTrackDrawable != null) {
1020661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette            mTrackDrawable.setState(myDrawableState);
1021661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette        }
102212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
102312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        invalidate();
102412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
102512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
1026cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette    @Override
10278de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette    public void drawableHotspotChanged(float x, float y) {
10288de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette        super.drawableHotspotChanged(x, y);
1029cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette
1030cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette        if (mThumbDrawable != null) {
1031cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette            mThumbDrawable.setHotspot(x, y);
1032cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette        }
1033cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette
1034cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette        if (mTrackDrawable != null) {
1035cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette            mTrackDrawable.setHotspot(x, y);
1036cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette        }
1037cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette    }
1038cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette
103912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
104012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    protected boolean verifyDrawable(Drawable who) {
104112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable;
104212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
104312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell
104412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    @Override
104512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    public void jumpDrawablesToCurrentState() {
104612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell        super.jumpDrawablesToCurrentState();
10474d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
10484d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        if (mThumbDrawable != null) {
10494d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            mThumbDrawable.jumpToCurrentState();
10504d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        }
10514d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
10524d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        if (mTrackDrawable != null) {
10534d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            mTrackDrawable.jumpToCurrentState();
10544d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        }
10554d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette
10564d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        if (mPositionAnimator != null && mPositionAnimator.isRunning()) {
10574d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            mPositionAnimator.end();
10584d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette            mPositionAnimator = null;
10594d065a04ce42c07569cf20651c949c4da97aa4a9Alan Viverette        }
106012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell    }
10618a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
10628a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
10638a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
10648a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityEvent(event);
10658a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        event.setClassName(Switch.class.getName());
10668a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
10678a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
10688a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
10698a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
10708a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityNodeInfo(info);
10718a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        info.setClassName(Switch.class.getName());
107278bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov        CharSequence switchText = isChecked() ? mTextOn : mTextOff;
107378bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov        if (!TextUtils.isEmpty(switchText)) {
107478bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov            CharSequence oldText = info.getText();
107578bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov            if (TextUtils.isEmpty(oldText)) {
107678bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov                info.setText(switchText);
107778bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov            } else {
107878bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov                StringBuilder newText = new StringBuilder();
107978bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov                newText.append(oldText).append(' ').append(switchText);
108078bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov                info.setText(newText);
108178bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov            }
108278bcc15b6c5959cc3eb9bbe2459af93451b74a22Svetoslav Ganov        }
10838a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
1084cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
1085cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    private static final FloatProperty<Switch> THUMB_POS = new FloatProperty<Switch>("thumbPos") {
1086cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        @Override
1087cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        public Float get(Switch object) {
1088cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette            return object.mThumbPosition;
1089cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        }
1090cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette
1091cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        @Override
1092cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        public void setValue(Switch object, float value) {
1093cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette            object.setThumbPosition(value);
1094cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette        }
1095cc2688d18af3f434fc6ac63289a69f6c1a9f8d9fAlan Viverette    };
109612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell}
1097