1af83b02b1d78576b685a116767d62df824fd285fPin Ting/*
2af83b02b1d78576b685a116767d62df824fd285fPin Ting * Copyright (C) 2012 The Android Open Source Project
3af83b02b1d78576b685a116767d62df824fd285fPin Ting *
4af83b02b1d78576b685a116767d62df824fd285fPin Ting * Licensed under the Apache License, Version 2.0 (the "License");
5af83b02b1d78576b685a116767d62df824fd285fPin Ting * you may not use this file except in compliance with the License.
6af83b02b1d78576b685a116767d62df824fd285fPin Ting * You may obtain a copy of the License at
7af83b02b1d78576b685a116767d62df824fd285fPin Ting *
8af83b02b1d78576b685a116767d62df824fd285fPin Ting *      http://www.apache.org/licenses/LICENSE-2.0
9af83b02b1d78576b685a116767d62df824fd285fPin Ting *
10af83b02b1d78576b685a116767d62df824fd285fPin Ting * Unless required by applicable law or agreed to in writing, software
11af83b02b1d78576b685a116767d62df824fd285fPin Ting * distributed under the License is distributed on an "AS IS" BASIS,
12af83b02b1d78576b685a116767d62df824fd285fPin Ting * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13af83b02b1d78576b685a116767d62df824fd285fPin Ting * See the License for the specific language governing permissions and
14af83b02b1d78576b685a116767d62df824fd285fPin Ting * limitations under the License.
15af83b02b1d78576b685a116767d62df824fd285fPin Ting */
16af83b02b1d78576b685a116767d62df824fd285fPin Ting
17af83b02b1d78576b685a116767d62df824fd285fPin Tingpackage com.android.camera.ui;
18af83b02b1d78576b685a116767d62df824fd285fPin Ting
192e6df147d54efb9c076647cb0fa3728322bdd16aPin Tingimport android.annotation.TargetApi;
20af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.content.Context;
21af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.content.res.ColorStateList;
22af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.content.res.Resources;
23af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.content.res.TypedArray;
24af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.graphics.Canvas;
25af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.graphics.Paint;
26af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.graphics.Rect;
27af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.graphics.Typeface;
28af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.graphics.drawable.Drawable;
29af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.text.Layout;
30af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.text.StaticLayout;
31af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.text.TextPaint;
32af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.text.TextUtils;
33af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.util.AttributeSet;
34af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.util.DisplayMetrics;
35af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.util.Log;
36af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.util.TypedValue;
37af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.view.Gravity;
38af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.view.MotionEvent;
39af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.view.VelocityTracker;
40af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.view.ViewConfiguration;
41af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.view.accessibility.AccessibilityEvent;
42af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.view.accessibility.AccessibilityNodeInfo;
43af83b02b1d78576b685a116767d62df824fd285fPin Tingimport android.widget.CompoundButton;
44af83b02b1d78576b685a116767d62df824fd285fPin Ting
45af83b02b1d78576b685a116767d62df824fd285fPin Tingimport com.android.camera.R;
462e6df147d54efb9c076647cb0fa3728322bdd16aPin Tingimport com.android.gallery3d.common.ApiHelper;
47af83b02b1d78576b685a116767d62df824fd285fPin Ting
48af83b02b1d78576b685a116767d62df824fd285fPin Tingimport java.util.Arrays;
49af83b02b1d78576b685a116767d62df824fd285fPin Ting
50af83b02b1d78576b685a116767d62df824fd285fPin Ting/**
51af83b02b1d78576b685a116767d62df824fd285fPin Ting * A Switch is a two-state toggle switch widget that can select between two
52af83b02b1d78576b685a116767d62df824fd285fPin Ting * options. The user may drag the "thumb" back and forth to choose the selected option,
53af83b02b1d78576b685a116767d62df824fd285fPin Ting * or simply tap to toggle as if it were a checkbox.
54af83b02b1d78576b685a116767d62df824fd285fPin Ting */
55af83b02b1d78576b685a116767d62df824fd285fPin Tingpublic class Switch extends CompoundButton {
56af83b02b1d78576b685a116767d62df824fd285fPin Ting    private static final int TOUCH_MODE_IDLE = 0;
57af83b02b1d78576b685a116767d62df824fd285fPin Ting    private static final int TOUCH_MODE_DOWN = 1;
58af83b02b1d78576b685a116767d62df824fd285fPin Ting    private static final int TOUCH_MODE_DRAGGING = 2;
59af83b02b1d78576b685a116767d62df824fd285fPin Ting
60af83b02b1d78576b685a116767d62df824fd285fPin Ting    private Drawable mThumbDrawable;
61af83b02b1d78576b685a116767d62df824fd285fPin Ting    private Drawable mTrackDrawable;
62af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mThumbTextPadding;
63af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mSwitchMinWidth;
64623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk    private int mSwitchTextMaxWidth;
65af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mSwitchPadding;
66af83b02b1d78576b685a116767d62df824fd285fPin Ting    private CharSequence mTextOn;
67af83b02b1d78576b685a116767d62df824fd285fPin Ting    private CharSequence mTextOff;
68af83b02b1d78576b685a116767d62df824fd285fPin Ting
69af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mTouchMode;
70af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mTouchSlop;
71af83b02b1d78576b685a116767d62df824fd285fPin Ting    private float mTouchX;
72af83b02b1d78576b685a116767d62df824fd285fPin Ting    private float mTouchY;
73af83b02b1d78576b685a116767d62df824fd285fPin Ting    private VelocityTracker mVelocityTracker = VelocityTracker.obtain();
74af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mMinFlingVelocity;
75af83b02b1d78576b685a116767d62df824fd285fPin Ting
76af83b02b1d78576b685a116767d62df824fd285fPin Ting    private float mThumbPosition;
77af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mSwitchWidth;
78af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mSwitchHeight;
79af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mThumbWidth; // Does not include padding
80af83b02b1d78576b685a116767d62df824fd285fPin Ting
81af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mSwitchLeft;
82af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mSwitchTop;
83af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mSwitchRight;
84af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int mSwitchBottom;
85af83b02b1d78576b685a116767d62df824fd285fPin Ting
86af83b02b1d78576b685a116767d62df824fd285fPin Ting    private TextPaint mTextPaint;
87af83b02b1d78576b685a116767d62df824fd285fPin Ting    private ColorStateList mTextColors;
88af83b02b1d78576b685a116767d62df824fd285fPin Ting    private Layout mOnLayout;
89af83b02b1d78576b685a116767d62df824fd285fPin Ting    private Layout mOffLayout;
90af83b02b1d78576b685a116767d62df824fd285fPin Ting
91af83b02b1d78576b685a116767d62df824fd285fPin Ting    @SuppressWarnings("hiding")
92af83b02b1d78576b685a116767d62df824fd285fPin Ting    private final Rect mTempRect = new Rect();
93af83b02b1d78576b685a116767d62df824fd285fPin Ting
94af83b02b1d78576b685a116767d62df824fd285fPin Ting    private static final int[] CHECKED_STATE_SET = {
95af83b02b1d78576b685a116767d62df824fd285fPin Ting        android.R.attr.state_checked
96af83b02b1d78576b685a116767d62df824fd285fPin Ting    };
97af83b02b1d78576b685a116767d62df824fd285fPin Ting
98af83b02b1d78576b685a116767d62df824fd285fPin Ting    /**
99af83b02b1d78576b685a116767d62df824fd285fPin Ting     * Construct a new Switch with default styling, overriding specific style
100af83b02b1d78576b685a116767d62df824fd285fPin Ting     * attributes as requested.
101af83b02b1d78576b685a116767d62df824fd285fPin Ting     *
102af83b02b1d78576b685a116767d62df824fd285fPin Ting     * @param context The Context that will determine this widget's theming.
103af83b02b1d78576b685a116767d62df824fd285fPin Ting     * @param attrs Specification of attributes that should deviate from default styling.
104af83b02b1d78576b685a116767d62df824fd285fPin Ting     */
105af83b02b1d78576b685a116767d62df824fd285fPin Ting    public Switch(Context context, AttributeSet attrs) {
106af83b02b1d78576b685a116767d62df824fd285fPin Ting        this(context, attrs, R.attr.switchStyle);
107af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
108af83b02b1d78576b685a116767d62df824fd285fPin Ting
109af83b02b1d78576b685a116767d62df824fd285fPin Ting    /**
110af83b02b1d78576b685a116767d62df824fd285fPin Ting     * Construct a new Switch with a default style determined by the given theme attribute,
111af83b02b1d78576b685a116767d62df824fd285fPin Ting     * overriding specific style attributes as requested.
112af83b02b1d78576b685a116767d62df824fd285fPin Ting     *
113af83b02b1d78576b685a116767d62df824fd285fPin Ting     * @param context The Context that will determine this widget's theming.
114af83b02b1d78576b685a116767d62df824fd285fPin Ting     * @param attrs Specification of attributes that should deviate from the default styling.
115af83b02b1d78576b685a116767d62df824fd285fPin Ting     * @param defStyle An attribute ID within the active theme containing a reference to the
116af83b02b1d78576b685a116767d62df824fd285fPin Ting     *                 default style for this widget. e.g. android.R.attr.switchStyle.
117af83b02b1d78576b685a116767d62df824fd285fPin Ting     */
118af83b02b1d78576b685a116767d62df824fd285fPin Ting    public Switch(Context context, AttributeSet attrs, int defStyle) {
119af83b02b1d78576b685a116767d62df824fd285fPin Ting        super(context, attrs, defStyle);
120af83b02b1d78576b685a116767d62df824fd285fPin Ting
121af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
122af83b02b1d78576b685a116767d62df824fd285fPin Ting        Resources res = getResources();
123af83b02b1d78576b685a116767d62df824fd285fPin Ting        DisplayMetrics dm = res.getDisplayMetrics();
124af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTextPaint.density = dm.density;
125af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbDrawable = res.getDrawable(R.drawable.switch_inner_holo_dark);
126af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTrackDrawable = res.getDrawable(R.drawable.switch_track_holo_dark);
127af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTextOn = res.getString(R.string.capital_on);
128af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTextOff = res.getString(R.string.capital_off);
129af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbTextPadding = res.getDimensionPixelSize(R.dimen.thumb_text_padding);
130af83b02b1d78576b685a116767d62df824fd285fPin Ting        mSwitchMinWidth = res.getDimensionPixelSize(R.dimen.switch_min_width);
131623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        mSwitchTextMaxWidth = res.getDimensionPixelSize(R.dimen.switch_text_max_width);
132af83b02b1d78576b685a116767d62df824fd285fPin Ting        mSwitchPadding = res.getDimensionPixelSize(R.dimen.switch_padding);
133af83b02b1d78576b685a116767d62df824fd285fPin Ting        setSwitchTextAppearance(context, android.R.style.TextAppearance_Holo_Small);
134af83b02b1d78576b685a116767d62df824fd285fPin Ting
135af83b02b1d78576b685a116767d62df824fd285fPin Ting        ViewConfiguration config = ViewConfiguration.get(context);
136af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTouchSlop = config.getScaledTouchSlop();
137af83b02b1d78576b685a116767d62df824fd285fPin Ting        mMinFlingVelocity = config.getScaledMinimumFlingVelocity();
138af83b02b1d78576b685a116767d62df824fd285fPin Ting
139af83b02b1d78576b685a116767d62df824fd285fPin Ting        // Refresh display with current params
140af83b02b1d78576b685a116767d62df824fd285fPin Ting        refreshDrawableState();
141af83b02b1d78576b685a116767d62df824fd285fPin Ting        setChecked(isChecked());
142af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
143af83b02b1d78576b685a116767d62df824fd285fPin Ting
144af83b02b1d78576b685a116767d62df824fd285fPin Ting    /**
145af83b02b1d78576b685a116767d62df824fd285fPin Ting     * Sets the switch text color, size, style, hint color, and highlight color
146af83b02b1d78576b685a116767d62df824fd285fPin Ting     * from the specified TextAppearance resource.
147af83b02b1d78576b685a116767d62df824fd285fPin Ting     */
148af83b02b1d78576b685a116767d62df824fd285fPin Ting    public void setSwitchTextAppearance(Context context, int resid) {
149af83b02b1d78576b685a116767d62df824fd285fPin Ting        Resources res = getResources();
150af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTextColors = getTextColors();
151af83b02b1d78576b685a116767d62df824fd285fPin Ting        int ts = res.getDimensionPixelSize(R.dimen.thumb_text_size);
152af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (ts != mTextPaint.getTextSize()) {
153af83b02b1d78576b685a116767d62df824fd285fPin Ting            mTextPaint.setTextSize(ts);
154af83b02b1d78576b685a116767d62df824fd285fPin Ting            requestLayout();
155af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
156af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
157af83b02b1d78576b685a116767d62df824fd285fPin Ting
158af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
159af83b02b1d78576b685a116767d62df824fd285fPin Ting    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
160623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
161623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
162af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (mOnLayout == null) {
163623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk            mOnLayout = makeLayout(mTextOn, mSwitchTextMaxWidth);
164af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
165af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (mOffLayout == null) {
166623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk            mOffLayout = makeLayout(mTextOff, mSwitchTextMaxWidth);
167af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
168af83b02b1d78576b685a116767d62df824fd285fPin Ting
169af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTrackDrawable.getPadding(mTempRect);
170623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        final int maxTextWidth = Math.min(mSwitchTextMaxWidth,
171623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk                Math.max(mOnLayout.getWidth(), mOffLayout.getWidth()));
172af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int switchWidth = Math.max(mSwitchMinWidth,
173af83b02b1d78576b685a116767d62df824fd285fPin Ting                maxTextWidth * 2 + mThumbTextPadding * 4 + mTempRect.left + mTempRect.right);
174af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int switchHeight = mTrackDrawable.getIntrinsicHeight();
175af83b02b1d78576b685a116767d62df824fd285fPin Ting
176af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbWidth = maxTextWidth + mThumbTextPadding * 2;
177af83b02b1d78576b685a116767d62df824fd285fPin Ting
178af83b02b1d78576b685a116767d62df824fd285fPin Ting        mSwitchWidth = switchWidth;
179af83b02b1d78576b685a116767d62df824fd285fPin Ting        mSwitchHeight = switchHeight;
180af83b02b1d78576b685a116767d62df824fd285fPin Ting
181af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
182af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int measuredHeight = getMeasuredHeight();
183623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        final int measuredWidth = getMeasuredWidth();
184af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (measuredHeight < switchHeight) {
185623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk            setMeasuredDimension(measuredWidth, switchHeight);
186af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
187af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
188af83b02b1d78576b685a116767d62df824fd285fPin Ting
1892e6df147d54efb9c076647cb0fa3728322bdd16aPin Ting    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
190af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
191af83b02b1d78576b685a116767d62df824fd285fPin Ting    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
192af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.onPopulateAccessibilityEvent(event);
193af83b02b1d78576b685a116767d62df824fd285fPin Ting        CharSequence text = isChecked() ? mOnLayout.getText() : mOffLayout.getText();
194af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (!TextUtils.isEmpty(text)) {
195af83b02b1d78576b685a116767d62df824fd285fPin Ting            event.getText().add(text);
196af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
197af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
198af83b02b1d78576b685a116767d62df824fd285fPin Ting
199623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk    private Layout makeLayout(CharSequence text, int maxWidth) {
200623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        int actual_width = (int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint));
201623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        StaticLayout l = new StaticLayout(text, 0, text.length(), mTextPaint,
202623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk                actual_width,
203623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk                Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true,
204623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk                TextUtils.TruncateAt.END,
205623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk                (int) Math.min(actual_width, maxWidth));
206623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        return l;
207af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
208af83b02b1d78576b685a116767d62df824fd285fPin Ting
209af83b02b1d78576b685a116767d62df824fd285fPin Ting    /**
210af83b02b1d78576b685a116767d62df824fd285fPin Ting     * @return true if (x, y) is within the target area of the switch thumb
211af83b02b1d78576b685a116767d62df824fd285fPin Ting     */
212af83b02b1d78576b685a116767d62df824fd285fPin Ting    private boolean hitThumb(float x, float y) {
213af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbDrawable.getPadding(mTempRect);
214af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int thumbTop = mSwitchTop - mTouchSlop;
215af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int thumbLeft = mSwitchLeft + (int) (mThumbPosition + 0.5f) - mTouchSlop;
216af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int thumbRight = thumbLeft + mThumbWidth +
217af83b02b1d78576b685a116767d62df824fd285fPin Ting                mTempRect.left + mTempRect.right + mTouchSlop;
218af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int thumbBottom = mSwitchBottom + mTouchSlop;
219af83b02b1d78576b685a116767d62df824fd285fPin Ting        return x > thumbLeft && x < thumbRight && y > thumbTop && y < thumbBottom;
220af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
221af83b02b1d78576b685a116767d62df824fd285fPin Ting
222af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
223af83b02b1d78576b685a116767d62df824fd285fPin Ting    public boolean onTouchEvent(MotionEvent ev) {
224af83b02b1d78576b685a116767d62df824fd285fPin Ting        mVelocityTracker.addMovement(ev);
225af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int action = ev.getActionMasked();
226af83b02b1d78576b685a116767d62df824fd285fPin Ting        switch (action) {
227af83b02b1d78576b685a116767d62df824fd285fPin Ting            case MotionEvent.ACTION_DOWN: {
228af83b02b1d78576b685a116767d62df824fd285fPin Ting                final float x = ev.getX();
229af83b02b1d78576b685a116767d62df824fd285fPin Ting                final float y = ev.getY();
230af83b02b1d78576b685a116767d62df824fd285fPin Ting                if (isEnabled() && hitThumb(x, y)) {
231af83b02b1d78576b685a116767d62df824fd285fPin Ting                    mTouchMode = TOUCH_MODE_DOWN;
232af83b02b1d78576b685a116767d62df824fd285fPin Ting                    mTouchX = x;
233af83b02b1d78576b685a116767d62df824fd285fPin Ting                    mTouchY = y;
234af83b02b1d78576b685a116767d62df824fd285fPin Ting                }
235af83b02b1d78576b685a116767d62df824fd285fPin Ting                break;
236af83b02b1d78576b685a116767d62df824fd285fPin Ting            }
237af83b02b1d78576b685a116767d62df824fd285fPin Ting
238af83b02b1d78576b685a116767d62df824fd285fPin Ting            case MotionEvent.ACTION_MOVE: {
239af83b02b1d78576b685a116767d62df824fd285fPin Ting                switch (mTouchMode) {
240af83b02b1d78576b685a116767d62df824fd285fPin Ting                    case TOUCH_MODE_IDLE:
241af83b02b1d78576b685a116767d62df824fd285fPin Ting                        // Didn't target the thumb, treat normally.
242af83b02b1d78576b685a116767d62df824fd285fPin Ting                        break;
243af83b02b1d78576b685a116767d62df824fd285fPin Ting
244af83b02b1d78576b685a116767d62df824fd285fPin Ting                    case TOUCH_MODE_DOWN: {
245af83b02b1d78576b685a116767d62df824fd285fPin Ting                        final float x = ev.getX();
246af83b02b1d78576b685a116767d62df824fd285fPin Ting                        final float y = ev.getY();
247af83b02b1d78576b685a116767d62df824fd285fPin Ting                        if (Math.abs(x - mTouchX) > mTouchSlop ||
248af83b02b1d78576b685a116767d62df824fd285fPin Ting                                Math.abs(y - mTouchY) > mTouchSlop) {
249af83b02b1d78576b685a116767d62df824fd285fPin Ting                            mTouchMode = TOUCH_MODE_DRAGGING;
250af83b02b1d78576b685a116767d62df824fd285fPin Ting                            getParent().requestDisallowInterceptTouchEvent(true);
251af83b02b1d78576b685a116767d62df824fd285fPin Ting                            mTouchX = x;
252af83b02b1d78576b685a116767d62df824fd285fPin Ting                            mTouchY = y;
253af83b02b1d78576b685a116767d62df824fd285fPin Ting                            return true;
254af83b02b1d78576b685a116767d62df824fd285fPin Ting                        }
255af83b02b1d78576b685a116767d62df824fd285fPin Ting                        break;
256af83b02b1d78576b685a116767d62df824fd285fPin Ting                    }
257af83b02b1d78576b685a116767d62df824fd285fPin Ting
258af83b02b1d78576b685a116767d62df824fd285fPin Ting                    case TOUCH_MODE_DRAGGING: {
259af83b02b1d78576b685a116767d62df824fd285fPin Ting                        final float x = ev.getX();
260af83b02b1d78576b685a116767d62df824fd285fPin Ting                        final float dx = x - mTouchX;
261af83b02b1d78576b685a116767d62df824fd285fPin Ting                        float newPos = Math.max(0,
262af83b02b1d78576b685a116767d62df824fd285fPin Ting                                Math.min(mThumbPosition + dx, getThumbScrollRange()));
263af83b02b1d78576b685a116767d62df824fd285fPin Ting                        if (newPos != mThumbPosition) {
264af83b02b1d78576b685a116767d62df824fd285fPin Ting                            mThumbPosition = newPos;
265af83b02b1d78576b685a116767d62df824fd285fPin Ting                            mTouchX = x;
266af83b02b1d78576b685a116767d62df824fd285fPin Ting                            invalidate();
267af83b02b1d78576b685a116767d62df824fd285fPin Ting                        }
268af83b02b1d78576b685a116767d62df824fd285fPin Ting                        return true;
269af83b02b1d78576b685a116767d62df824fd285fPin Ting                    }
270af83b02b1d78576b685a116767d62df824fd285fPin Ting                }
271af83b02b1d78576b685a116767d62df824fd285fPin Ting                break;
272af83b02b1d78576b685a116767d62df824fd285fPin Ting            }
273af83b02b1d78576b685a116767d62df824fd285fPin Ting
274af83b02b1d78576b685a116767d62df824fd285fPin Ting            case MotionEvent.ACTION_UP:
275af83b02b1d78576b685a116767d62df824fd285fPin Ting            case MotionEvent.ACTION_CANCEL: {
276af83b02b1d78576b685a116767d62df824fd285fPin Ting                if (mTouchMode == TOUCH_MODE_DRAGGING) {
277af83b02b1d78576b685a116767d62df824fd285fPin Ting                    stopDrag(ev);
278af83b02b1d78576b685a116767d62df824fd285fPin Ting                    return true;
279af83b02b1d78576b685a116767d62df824fd285fPin Ting                }
280af83b02b1d78576b685a116767d62df824fd285fPin Ting                mTouchMode = TOUCH_MODE_IDLE;
281af83b02b1d78576b685a116767d62df824fd285fPin Ting                mVelocityTracker.clear();
282af83b02b1d78576b685a116767d62df824fd285fPin Ting                break;
283af83b02b1d78576b685a116767d62df824fd285fPin Ting            }
284af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
285af83b02b1d78576b685a116767d62df824fd285fPin Ting
286af83b02b1d78576b685a116767d62df824fd285fPin Ting        return super.onTouchEvent(ev);
287af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
288af83b02b1d78576b685a116767d62df824fd285fPin Ting
289af83b02b1d78576b685a116767d62df824fd285fPin Ting    private void cancelSuperTouch(MotionEvent ev) {
290af83b02b1d78576b685a116767d62df824fd285fPin Ting        MotionEvent cancel = MotionEvent.obtain(ev);
291af83b02b1d78576b685a116767d62df824fd285fPin Ting        cancel.setAction(MotionEvent.ACTION_CANCEL);
292af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.onTouchEvent(cancel);
293af83b02b1d78576b685a116767d62df824fd285fPin Ting        cancel.recycle();
294af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
295af83b02b1d78576b685a116767d62df824fd285fPin Ting
296af83b02b1d78576b685a116767d62df824fd285fPin Ting    /**
297af83b02b1d78576b685a116767d62df824fd285fPin Ting     * Called from onTouchEvent to end a drag operation.
298af83b02b1d78576b685a116767d62df824fd285fPin Ting     *
299af83b02b1d78576b685a116767d62df824fd285fPin Ting     * @param ev Event that triggered the end of drag mode - ACTION_UP or ACTION_CANCEL
300af83b02b1d78576b685a116767d62df824fd285fPin Ting     */
301af83b02b1d78576b685a116767d62df824fd285fPin Ting    private void stopDrag(MotionEvent ev) {
302af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTouchMode = TOUCH_MODE_IDLE;
303af83b02b1d78576b685a116767d62df824fd285fPin Ting        // Up and not canceled, also checks the switch has not been disabled during the drag
304af83b02b1d78576b685a116767d62df824fd285fPin Ting        boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP && isEnabled();
305af83b02b1d78576b685a116767d62df824fd285fPin Ting
306af83b02b1d78576b685a116767d62df824fd285fPin Ting        cancelSuperTouch(ev);
307af83b02b1d78576b685a116767d62df824fd285fPin Ting
308af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (commitChange) {
309af83b02b1d78576b685a116767d62df824fd285fPin Ting            boolean newState;
310af83b02b1d78576b685a116767d62df824fd285fPin Ting            mVelocityTracker.computeCurrentVelocity(1000);
311af83b02b1d78576b685a116767d62df824fd285fPin Ting            float xvel = mVelocityTracker.getXVelocity();
312af83b02b1d78576b685a116767d62df824fd285fPin Ting            if (Math.abs(xvel) > mMinFlingVelocity) {
313af83b02b1d78576b685a116767d62df824fd285fPin Ting                newState = xvel > 0;
314af83b02b1d78576b685a116767d62df824fd285fPin Ting            } else {
315af83b02b1d78576b685a116767d62df824fd285fPin Ting                newState = getTargetCheckedState();
316af83b02b1d78576b685a116767d62df824fd285fPin Ting            }
317af83b02b1d78576b685a116767d62df824fd285fPin Ting            animateThumbToCheckedState(newState);
318af83b02b1d78576b685a116767d62df824fd285fPin Ting        } else {
319af83b02b1d78576b685a116767d62df824fd285fPin Ting            animateThumbToCheckedState(isChecked());
320af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
321af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
322af83b02b1d78576b685a116767d62df824fd285fPin Ting
323af83b02b1d78576b685a116767d62df824fd285fPin Ting    private void animateThumbToCheckedState(boolean newCheckedState) {
324af83b02b1d78576b685a116767d62df824fd285fPin Ting        setChecked(newCheckedState);
325af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
326af83b02b1d78576b685a116767d62df824fd285fPin Ting
327af83b02b1d78576b685a116767d62df824fd285fPin Ting    private boolean getTargetCheckedState() {
328af83b02b1d78576b685a116767d62df824fd285fPin Ting        return mThumbPosition >= getThumbScrollRange() / 2;
329af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
330af83b02b1d78576b685a116767d62df824fd285fPin Ting
331af83b02b1d78576b685a116767d62df824fd285fPin Ting    private void setThumbPosition(boolean checked) {
332af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbPosition = checked ? getThumbScrollRange() : 0;
333af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
334af83b02b1d78576b685a116767d62df824fd285fPin Ting
335af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
336af83b02b1d78576b685a116767d62df824fd285fPin Ting    public void setChecked(boolean checked) {
337af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.setChecked(checked);
338af83b02b1d78576b685a116767d62df824fd285fPin Ting        setThumbPosition(checked);
339af83b02b1d78576b685a116767d62df824fd285fPin Ting        invalidate();
340af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
341af83b02b1d78576b685a116767d62df824fd285fPin Ting
342af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
343af83b02b1d78576b685a116767d62df824fd285fPin Ting    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
344af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.onLayout(changed, left, top, right, bottom);
345af83b02b1d78576b685a116767d62df824fd285fPin Ting
346af83b02b1d78576b685a116767d62df824fd285fPin Ting        setThumbPosition(isChecked());
347af83b02b1d78576b685a116767d62df824fd285fPin Ting
348af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchRight;
349af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchLeft;
350af83b02b1d78576b685a116767d62df824fd285fPin Ting
351af83b02b1d78576b685a116767d62df824fd285fPin Ting        switchRight = getWidth() - getPaddingRight();
352af83b02b1d78576b685a116767d62df824fd285fPin Ting        switchLeft = switchRight - mSwitchWidth;
353af83b02b1d78576b685a116767d62df824fd285fPin Ting
354af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchTop = 0;
355af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchBottom = 0;
356af83b02b1d78576b685a116767d62df824fd285fPin Ting        switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) {
357af83b02b1d78576b685a116767d62df824fd285fPin Ting            default:
358af83b02b1d78576b685a116767d62df824fd285fPin Ting            case Gravity.TOP:
359af83b02b1d78576b685a116767d62df824fd285fPin Ting                switchTop = getPaddingTop();
360af83b02b1d78576b685a116767d62df824fd285fPin Ting                switchBottom = switchTop + mSwitchHeight;
361af83b02b1d78576b685a116767d62df824fd285fPin Ting                break;
362af83b02b1d78576b685a116767d62df824fd285fPin Ting
363af83b02b1d78576b685a116767d62df824fd285fPin Ting            case Gravity.CENTER_VERTICAL:
364af83b02b1d78576b685a116767d62df824fd285fPin Ting                switchTop = (getPaddingTop() + getHeight() - getPaddingBottom()) / 2 -
365af83b02b1d78576b685a116767d62df824fd285fPin Ting                        mSwitchHeight / 2;
366af83b02b1d78576b685a116767d62df824fd285fPin Ting                switchBottom = switchTop + mSwitchHeight;
367af83b02b1d78576b685a116767d62df824fd285fPin Ting                break;
368af83b02b1d78576b685a116767d62df824fd285fPin Ting
369af83b02b1d78576b685a116767d62df824fd285fPin Ting            case Gravity.BOTTOM:
370af83b02b1d78576b685a116767d62df824fd285fPin Ting                switchBottom = getHeight() - getPaddingBottom();
371af83b02b1d78576b685a116767d62df824fd285fPin Ting                switchTop = switchBottom - mSwitchHeight;
372af83b02b1d78576b685a116767d62df824fd285fPin Ting                break;
373af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
374af83b02b1d78576b685a116767d62df824fd285fPin Ting
375af83b02b1d78576b685a116767d62df824fd285fPin Ting        mSwitchLeft = switchLeft;
376af83b02b1d78576b685a116767d62df824fd285fPin Ting        mSwitchTop = switchTop;
377af83b02b1d78576b685a116767d62df824fd285fPin Ting        mSwitchBottom = switchBottom;
378af83b02b1d78576b685a116767d62df824fd285fPin Ting        mSwitchRight = switchRight;
379af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
380af83b02b1d78576b685a116767d62df824fd285fPin Ting
381af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
382af83b02b1d78576b685a116767d62df824fd285fPin Ting    protected void onDraw(Canvas canvas) {
383af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.onDraw(canvas);
384af83b02b1d78576b685a116767d62df824fd285fPin Ting
385af83b02b1d78576b685a116767d62df824fd285fPin Ting        // Draw the switch
386af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchLeft = mSwitchLeft;
387af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchTop = mSwitchTop;
388af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchRight = mSwitchRight;
389af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchBottom = mSwitchBottom;
390af83b02b1d78576b685a116767d62df824fd285fPin Ting
391af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTrackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom);
392af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTrackDrawable.draw(canvas);
393af83b02b1d78576b685a116767d62df824fd285fPin Ting
394af83b02b1d78576b685a116767d62df824fd285fPin Ting        canvas.save();
395af83b02b1d78576b685a116767d62df824fd285fPin Ting
396af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTrackDrawable.getPadding(mTempRect);
397af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchInnerLeft = switchLeft + mTempRect.left;
398af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchInnerTop = switchTop + mTempRect.top;
399af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchInnerRight = switchRight - mTempRect.right;
400af83b02b1d78576b685a116767d62df824fd285fPin Ting        int switchInnerBottom = switchBottom - mTempRect.bottom;
401af83b02b1d78576b685a116767d62df824fd285fPin Ting        canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
402af83b02b1d78576b685a116767d62df824fd285fPin Ting
403af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbDrawable.getPadding(mTempRect);
404af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int thumbPos = (int) (mThumbPosition + 0.5f);
405af83b02b1d78576b685a116767d62df824fd285fPin Ting        int thumbLeft = switchInnerLeft - mTempRect.left + thumbPos;
406af83b02b1d78576b685a116767d62df824fd285fPin Ting        int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + mTempRect.right;
407af83b02b1d78576b685a116767d62df824fd285fPin Ting
408af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);
409af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbDrawable.draw(canvas);
410af83b02b1d78576b685a116767d62df824fd285fPin Ting
411af83b02b1d78576b685a116767d62df824fd285fPin Ting        // mTextColors should not be null, but just in case
412af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (mTextColors != null) {
413af83b02b1d78576b685a116767d62df824fd285fPin Ting            mTextPaint.setColor(mTextColors.getColorForState(getDrawableState(),
414af83b02b1d78576b685a116767d62df824fd285fPin Ting                    mTextColors.getDefaultColor()));
415af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
416af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTextPaint.drawableState = getDrawableState();
417af83b02b1d78576b685a116767d62df824fd285fPin Ting
418af83b02b1d78576b685a116767d62df824fd285fPin Ting        Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
419af83b02b1d78576b685a116767d62df824fd285fPin Ting
420623cb339185cbab100fb05c5d9ab3c8c795e5339Ruben Brunk        canvas.translate((thumbLeft + thumbRight) / 2 - switchText.getEllipsizedWidth() / 2,
421af83b02b1d78576b685a116767d62df824fd285fPin Ting                (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2);
422af83b02b1d78576b685a116767d62df824fd285fPin Ting        switchText.draw(canvas);
423af83b02b1d78576b685a116767d62df824fd285fPin Ting
424af83b02b1d78576b685a116767d62df824fd285fPin Ting        canvas.restore();
425af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
426af83b02b1d78576b685a116767d62df824fd285fPin Ting
427af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
428af83b02b1d78576b685a116767d62df824fd285fPin Ting    public int getCompoundPaddingRight() {
429af83b02b1d78576b685a116767d62df824fd285fPin Ting        int padding = super.getCompoundPaddingRight() + mSwitchWidth;
430af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (!TextUtils.isEmpty(getText())) {
431af83b02b1d78576b685a116767d62df824fd285fPin Ting            padding += mSwitchPadding;
432af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
433af83b02b1d78576b685a116767d62df824fd285fPin Ting        return padding;
434af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
435af83b02b1d78576b685a116767d62df824fd285fPin Ting
436af83b02b1d78576b685a116767d62df824fd285fPin Ting    private int getThumbScrollRange() {
437af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (mTrackDrawable == null) {
438af83b02b1d78576b685a116767d62df824fd285fPin Ting            return 0;
439af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
440af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTrackDrawable.getPadding(mTempRect);
441af83b02b1d78576b685a116767d62df824fd285fPin Ting        return mSwitchWidth - mThumbWidth - mTempRect.left - mTempRect.right;
442af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
443af83b02b1d78576b685a116767d62df824fd285fPin Ting
444af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
445af83b02b1d78576b685a116767d62df824fd285fPin Ting    protected int[] onCreateDrawableState(int extraSpace) {
446af83b02b1d78576b685a116767d62df824fd285fPin Ting        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
447af83b02b1d78576b685a116767d62df824fd285fPin Ting
448af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (isChecked()) {
449af83b02b1d78576b685a116767d62df824fd285fPin Ting            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
450af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
451af83b02b1d78576b685a116767d62df824fd285fPin Ting        return drawableState;
452af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
453af83b02b1d78576b685a116767d62df824fd285fPin Ting
454af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
455af83b02b1d78576b685a116767d62df824fd285fPin Ting    protected void drawableStateChanged() {
456af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.drawableStateChanged();
457af83b02b1d78576b685a116767d62df824fd285fPin Ting
458af83b02b1d78576b685a116767d62df824fd285fPin Ting        int[] myDrawableState = getDrawableState();
459af83b02b1d78576b685a116767d62df824fd285fPin Ting
460af83b02b1d78576b685a116767d62df824fd285fPin Ting        // Set the state of the Drawable
461af83b02b1d78576b685a116767d62df824fd285fPin Ting        // Drawable may be null when checked state is set from XML, from super constructor
462af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (mThumbDrawable != null) mThumbDrawable.setState(myDrawableState);
463af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (mTrackDrawable != null) mTrackDrawable.setState(myDrawableState);
464af83b02b1d78576b685a116767d62df824fd285fPin Ting
465af83b02b1d78576b685a116767d62df824fd285fPin Ting        invalidate();
466af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
467af83b02b1d78576b685a116767d62df824fd285fPin Ting
468af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
469af83b02b1d78576b685a116767d62df824fd285fPin Ting    protected boolean verifyDrawable(Drawable who) {
470af83b02b1d78576b685a116767d62df824fd285fPin Ting        return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable;
471af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
472af83b02b1d78576b685a116767d62df824fd285fPin Ting
4732e6df147d54efb9c076647cb0fa3728322bdd16aPin Ting    @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
474af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
475af83b02b1d78576b685a116767d62df824fd285fPin Ting    public void jumpDrawablesToCurrentState() {
476af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.jumpDrawablesToCurrentState();
477af83b02b1d78576b685a116767d62df824fd285fPin Ting        mThumbDrawable.jumpToCurrentState();
478af83b02b1d78576b685a116767d62df824fd285fPin Ting        mTrackDrawable.jumpToCurrentState();
479af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
480af83b02b1d78576b685a116767d62df824fd285fPin Ting
4812e6df147d54efb9c076647cb0fa3728322bdd16aPin Ting    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
482af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
483af83b02b1d78576b685a116767d62df824fd285fPin Ting    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
484af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.onInitializeAccessibilityEvent(event);
485af83b02b1d78576b685a116767d62df824fd285fPin Ting        event.setClassName(Switch.class.getName());
486af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
487af83b02b1d78576b685a116767d62df824fd285fPin Ting
4882e6df147d54efb9c076647cb0fa3728322bdd16aPin Ting    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
489af83b02b1d78576b685a116767d62df824fd285fPin Ting    @Override
490af83b02b1d78576b685a116767d62df824fd285fPin Ting    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
491af83b02b1d78576b685a116767d62df824fd285fPin Ting        super.onInitializeAccessibilityNodeInfo(info);
492af83b02b1d78576b685a116767d62df824fd285fPin Ting        info.setClassName(Switch.class.getName());
493af83b02b1d78576b685a116767d62df824fd285fPin Ting        CharSequence switchText = isChecked() ? mTextOn : mTextOff;
494af83b02b1d78576b685a116767d62df824fd285fPin Ting        if (!TextUtils.isEmpty(switchText)) {
495af83b02b1d78576b685a116767d62df824fd285fPin Ting            CharSequence oldText = info.getText();
496af83b02b1d78576b685a116767d62df824fd285fPin Ting            if (TextUtils.isEmpty(oldText)) {
497af83b02b1d78576b685a116767d62df824fd285fPin Ting                info.setText(switchText);
498af83b02b1d78576b685a116767d62df824fd285fPin Ting            } else {
499af83b02b1d78576b685a116767d62df824fd285fPin Ting                StringBuilder newText = new StringBuilder();
500af83b02b1d78576b685a116767d62df824fd285fPin Ting                newText.append(oldText).append(' ').append(switchText);
501af83b02b1d78576b685a116767d62df824fd285fPin Ting                info.setText(newText);
502af83b02b1d78576b685a116767d62df824fd285fPin Ting            }
503af83b02b1d78576b685a116767d62df824fd285fPin Ting        }
504af83b02b1d78576b685a116767d62df824fd285fPin Ting    }
505af83b02b1d78576b685a116767d62df824fd285fPin Ting}
506