Switch.java revision 63bce03cc69be4a45230aa8bbd89dbde60681067
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 1912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.Context; 2012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.ColorStateList; 2112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.Resources; 2212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.content.res.TypedArray; 2312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Canvas; 2412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Paint; 2512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Rect; 2612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.Typeface; 2712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.graphics.drawable.Drawable; 2812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.Layout; 2912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.StaticLayout; 3012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.TextPaint; 3112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.text.TextUtils; 3212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.util.AttributeSet; 3312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.Gravity; 3412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.MotionEvent; 3512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.VelocityTracker; 3612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellimport android.view.ViewConfiguration; 3763bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 3812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 39be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powellimport com.android.internal.R; 40be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powell 4112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell/** 4212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * A Switch is a two-state toggle switch widget that can select between two 4312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * options. The user may drag the "thumb" back and forth to choose the selected option, 4412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * or simply tap to toggle as if it were a checkbox. 4512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 4612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @hide 4712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 4812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powellpublic class Switch extends CompoundButton { 4912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int TOUCH_MODE_IDLE = 0; 5012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int TOUCH_MODE_DOWN = 1; 5112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int TOUCH_MODE_DRAGGING = 2; 5212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 5312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Enum for the "typeface" XML parameter. 5412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int SANS = 1; 5512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int SERIF = 2; 5612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int MONOSPACE = 3; 5712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 5812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Drawable mThumbDrawable; 5912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Drawable mTrackDrawable; 6012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mThumbTextPadding; 6112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchMinWidth; 6212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchPadding; 6312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private CharSequence mTextOn; 6412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private CharSequence mTextOff; 6512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 6612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mTouchMode; 6712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mTouchSlop; 6812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private float mTouchX; 6912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private float mTouchY; 7012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private VelocityTracker mVelocityTracker = VelocityTracker.obtain(); 7112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mMinFlingVelocity; 7212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 7312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private float mThumbPosition; 7412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchWidth; 7512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchHeight; 7612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mThumbWidth; // Does not include padding 7712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 7812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchLeft; 7912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchTop; 8012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchRight; 8112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int mSwitchBottom; 8212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 8312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private TextPaint mTextPaint; 8412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private ColorStateList mTextColors; 8512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Layout mOnLayout; 8612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Layout mOffLayout; 8712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 88be0a4535053bbfdebd215e244b154ac810fd8edcAdam Powell @SuppressWarnings("hiding") 8912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private final Rect mTempRect = new Rect(); 9012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 9112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private static final int[] CHECKED_STATE_SET = { 9212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell R.attr.state_checked 9312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell }; 9412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 9512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 9612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Construct a new Switch with default styling. 9712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 9812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param context The Context that will determine this widget's theming. 9912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 10012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public Switch(Context context) { 10112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell this(context, null); 10212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 10312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 10412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 10512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Construct a new Switch with default styling, overriding specific style 10612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * attributes as requested. 10712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 10812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param context The Context that will determine this widget's theming. 10912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param attrs Specification of attributes that should deviate from default styling. 11012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 11112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public Switch(Context context, AttributeSet attrs) { 11212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell this(context, attrs, com.android.internal.R.attr.switchStyle); 11312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 11412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 11512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 11612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Construct a new Switch with a default style determined by the given theme attribute, 11712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * overriding specific style attributes as requested. 11812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 11912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param context The Context that will determine this widget's theming. 12012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param attrs Specification of attributes that should deviate from the default styling. 12112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param defStyle An attribute ID within the active theme containing a reference to the 12212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * default style for this widget. e.g. android.R.attr.switchStyle. 12312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 12412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public Switch(Context context, AttributeSet attrs, int defStyle) { 12512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super(context, attrs, defStyle); 12612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 12712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); 12812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Resources res = getResources(); 12912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.density = res.getDisplayMetrics().density; 13012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale); 13112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 13212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TypedArray a = context.obtainStyledAttributes(attrs, 13312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch, defStyle, 0); 13412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 13512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_switchThumb); 13612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTrackDrawable = a.getDrawable(com.android.internal.R.styleable.Switch_switchTrack); 13712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextOn = a.getText(com.android.internal.R.styleable.Switch_textOn); 13812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextOff = a.getText(com.android.internal.R.styleable.Switch_textOff); 13912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbTextPadding = a.getDimensionPixelSize( 14012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch_thumbTextPadding, 0); 14112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchMinWidth = a.getDimensionPixelSize( 14212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch_switchMinWidth, 0); 14312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchPadding = a.getDimensionPixelSize( 14412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch_switchPadding, 0); 14512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 14612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int appearance = a.getResourceId( 14712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.Switch_switchTextAppearance, 0); 14812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (appearance != 0) { 14912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTextAppearance(appearance); 15012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 15112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell a.recycle(); 15212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 15312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell ViewConfiguration config = ViewConfiguration.get(context); 15412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchSlop = config.getScaledTouchSlop(); 15512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mMinFlingVelocity = config.getScaledMinimumFlingVelocity(); 15612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 15712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Refresh display with current params 15812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setChecked(isChecked()); 15912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 16012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 16112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 16212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Sets the switch text color, size, style, hint color, and highlight color 16312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * from the specified TextAppearance resource. 16412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 16512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setSwitchTextAppearance(int resid) { 16612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TypedArray appearance = 16712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell getContext().obtainStyledAttributes(resid, 16812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell com.android.internal.R.styleable.TextAppearance); 16912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 17012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell ColorStateList colors; 17112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int ts; 17212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 17312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell colors = appearance.getColorStateList(com.android.internal.R.styleable. 17412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TextAppearance_textColor); 17512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (colors != null) { 17612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextColors = colors; 17712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 17812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 17912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell ts = appearance.getDimensionPixelSize(com.android.internal.R.styleable. 18012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TextAppearance_textSize, 0); 18112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (ts != 0) { 18212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (ts != mTextPaint.getTextSize()) { 18312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setTextSize(ts); 18412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell requestLayout(); 18512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 18612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 18712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 18812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int typefaceIndex, styleIndex; 18912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 19012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell typefaceIndex = appearance.getInt(com.android.internal.R.styleable. 19112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TextAppearance_typeface, -1); 19212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell styleIndex = appearance.getInt(com.android.internal.R.styleable. 19312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell TextAppearance_textStyle, -1); 19412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 19512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTypefaceByIndex(typefaceIndex, styleIndex); 19612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 19712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell appearance.recycle(); 19812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 19912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 20012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private void setSwitchTypefaceByIndex(int typefaceIndex, int styleIndex) { 20112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Typeface tf = null; 20212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (typefaceIndex) { 20312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case SANS: 20412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.SANS_SERIF; 20512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 20612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 20712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case SERIF: 20812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.SERIF; 20912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 21012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 21112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MONOSPACE: 21212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.MONOSPACE; 21312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 21412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 21512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 21612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTypeface(tf, styleIndex); 21712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 21812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 21912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 22012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Sets the typeface and style in which the text should be displayed on the 22112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * switch, and turns on the fake bold and italic bits in the Paint if the 22212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Typeface that you provided does not have all the bits in the 22312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * style that you specified. 22412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 22512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setSwitchTypeface(Typeface tf, int style) { 22612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (style > 0) { 22712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (tf == null) { 22812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.defaultFromStyle(style); 22912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } else { 23012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell tf = Typeface.create(tf, style); 23112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 23212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 23312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTypeface(tf); 23412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // now compute what (if any) algorithmic styling is needed 23512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int typefaceStyle = tf != null ? tf.getStyle() : 0; 23612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int need = style & ~typefaceStyle; 23712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setFakeBoldText((need & Typeface.BOLD) != 0); 23812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0); 23912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } else { 24012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setFakeBoldText(false); 24112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setTextSkewX(0); 24212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setSwitchTypeface(tf); 24312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 24412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 24512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 24612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 24712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Sets the typeface and style in which the text should be displayed on the switch. 24812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Note that not all Typeface families actually have bold and italic 24912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * variants, so you may need to use 25012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * {@link #setSwitchTypeface(Typeface, int)} to get the appearance 25112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * that you actually want. 25212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 25312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @attr ref android.R.styleable#TextView_typeface 25412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @attr ref android.R.styleable#TextView_textStyle 25512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 25612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setSwitchTypeface(Typeface tf) { 25712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (mTextPaint.getTypeface() != tf) { 25812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setTypeface(tf); 25912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 26012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell requestLayout(); 26112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell invalidate(); 26212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 26312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 26412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 26512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 26612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Returns the text for when the button is in the checked state. 26712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 26812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @return The text. 26912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 27012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public CharSequence getTextOn() { 27112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return mTextOn; 27212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 27312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 27412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 27512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Sets the text for when the button is in the checked state. 27612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 27712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param textOn The text. 27812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 27912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setTextOn(CharSequence textOn) { 28012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextOn = textOn; 28112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell requestLayout(); 28212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 28312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 28412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 28512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Returns the text for when the button is not in the checked state. 28612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 28712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @return The text. 28812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 28912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public CharSequence getTextOff() { 29012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return mTextOff; 29112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 29212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 29312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 29412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Sets the text for when the button is not in the checked state. 29512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 29612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param textOff The text. 29712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 29812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setTextOff(CharSequence textOff) { 29912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextOff = textOff; 30012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell requestLayout(); 30112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 30212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 30312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 30412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 30512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 30612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 30712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int widthSize = MeasureSpec.getSize(widthMeasureSpec); 30812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int heightSize = MeasureSpec.getSize(heightMeasureSpec); 30912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 31012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 31112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (mOnLayout == null) { 31212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mOnLayout = makeLayout(mTextOn); 31312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 31412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (mOffLayout == null) { 31512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mOffLayout = makeLayout(mTextOff); 31612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 31712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 31812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTrackDrawable.getPadding(mTempRect); 31912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth()); 32012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int switchWidth = Math.max(mSwitchMinWidth, 32112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell maxTextWidth * 2 + mThumbTextPadding * 4 + mTempRect.left + mTempRect.right); 32212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int switchHeight = mTrackDrawable.getIntrinsicHeight(); 32312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 32412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbWidth = maxTextWidth + mThumbTextPadding * 2; 32512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 32612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (widthMode) { 32712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MeasureSpec.AT_MOST: 32812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell widthSize = Math.min(widthSize, switchWidth); 32912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 33012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 33112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MeasureSpec.UNSPECIFIED: 33212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell widthSize = switchWidth; 33312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 33412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 33512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MeasureSpec.EXACTLY: 33612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Just use what we were given 33712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 33812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 33912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 34012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (heightMode) { 34112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MeasureSpec.AT_MOST: 34212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell heightSize = Math.min(heightSize, switchHeight); 34312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 34412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 34512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MeasureSpec.UNSPECIFIED: 34612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell heightSize = switchHeight; 34712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 34812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 34912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MeasureSpec.EXACTLY: 35012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Just use what we were given 35112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 35212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 35312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 35412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchWidth = switchWidth; 35512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchHeight = switchHeight; 35612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 35712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.onMeasure(widthMeasureSpec, heightMeasureSpec); 35812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int measuredHeight = getMeasuredHeight(); 35912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (measuredHeight < switchHeight) { 360189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn setMeasuredDimension(getMeasuredWidthAndState(), switchHeight); 36112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 36212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 36312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 36463bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov @Override 36563bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 36663bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov super.onPopulateAccessibilityEvent(event); 36763bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout; 36863bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov event.getText().add(switchText.getText()); 36963bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov } 37063bce03cc69be4a45230aa8bbd89dbde60681067Svetoslav Ganov 37112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private Layout makeLayout(CharSequence text) { 37212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return new StaticLayout(text, mTextPaint, 37312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell (int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)), 37412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true); 37512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 37612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 37712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 37812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @return true if (x, y) is within the target area of the switch thumb 37912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 38012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private boolean hitThumb(float x, float y) { 38112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbDrawable.getPadding(mTempRect); 38212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int thumbTop = mSwitchTop - mTouchSlop; 38312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int thumbLeft = mSwitchLeft + (int) (mThumbPosition + 0.5f) - mTouchSlop; 38412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int thumbRight = thumbLeft + mThumbWidth + 38512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTempRect.left + mTempRect.right + mTouchSlop; 38612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int thumbBottom = mSwitchBottom + mTouchSlop; 38712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return x > thumbLeft && x < thumbRight && y > thumbTop && y < thumbBottom; 38812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 38912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 39012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 39112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public boolean onTouchEvent(MotionEvent ev) { 39212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mVelocityTracker.addMovement(ev); 39312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int action = ev.getActionMasked(); 39412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (action) { 39512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MotionEvent.ACTION_DOWN: { 39612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float x = ev.getX(); 39712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float y = ev.getY(); 398c2ab0d665c9d1c332fbd726abf582a27cf7a6701Gilles Debunne if (isEnabled() && hitThumb(x, y)) { 39912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchMode = TOUCH_MODE_DOWN; 40012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchX = x; 40112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchY = y; 40212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 40312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 40412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 40512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 40612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MotionEvent.ACTION_MOVE: { 40712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (mTouchMode) { 40812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case TOUCH_MODE_IDLE: 40912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Didn't target the thumb, treat normally. 41012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 41112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 41212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case TOUCH_MODE_DOWN: { 41312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float x = ev.getX(); 41412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float y = ev.getY(); 41512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (Math.abs(x - mTouchX) > mTouchSlop || 41612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Math.abs(y - mTouchY) > mTouchSlop) { 41712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchMode = TOUCH_MODE_DRAGGING; 41812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell getParent().requestDisallowInterceptTouchEvent(true); 41912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchX = x; 42012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchY = y; 42112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return true; 42212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 42312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 42412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 42512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 42612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case TOUCH_MODE_DRAGGING: { 42712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float x = ev.getX(); 42812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final float dx = x - mTouchX; 42912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell float newPos = Math.max(0, 43012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Math.min(mThumbPosition + dx, getThumbScrollRange())); 43112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (newPos != mThumbPosition) { 43212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbPosition = newPos; 43312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchX = x; 43412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell invalidate(); 43512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 43612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return true; 43712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 43812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 43912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 44012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 44112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 44212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MotionEvent.ACTION_UP: 44312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case MotionEvent.ACTION_CANCEL: { 44412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (mTouchMode == TOUCH_MODE_DRAGGING) { 44512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell stopDrag(ev); 44612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return true; 44712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 44812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchMode = TOUCH_MODE_IDLE; 44912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mVelocityTracker.clear(); 45012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 45112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 45212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 45312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 45412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return super.onTouchEvent(ev); 45512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 45612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 45712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private void cancelSuperTouch(MotionEvent ev) { 45812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell MotionEvent cancel = MotionEvent.obtain(ev); 45912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell cancel.setAction(MotionEvent.ACTION_CANCEL); 46012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.onTouchEvent(cancel); 46112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell cancel.recycle(); 46212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 46312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 46412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell /** 46512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * Called from onTouchEvent to end a drag operation. 46612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * 46712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell * @param ev Event that triggered the end of drag mode - ACTION_UP or ACTION_CANCEL 46812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell */ 46912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private void stopDrag(MotionEvent ev) { 47012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTouchMode = TOUCH_MODE_IDLE; 471c2ab0d665c9d1c332fbd726abf582a27cf7a6701Gilles Debunne // Up and not canceled, also checks the switch has not been disabled during the drag 472c2ab0d665c9d1c332fbd726abf582a27cf7a6701Gilles Debunne boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP && isEnabled(); 47312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 47412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell cancelSuperTouch(ev); 47512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 47612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (commitChange) { 47712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell boolean newState; 47812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mVelocityTracker.computeCurrentVelocity(1000); 47912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell float xvel = mVelocityTracker.getXVelocity(); 48012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (Math.abs(xvel) > mMinFlingVelocity) { 48112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell newState = xvel < 0; 48212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } else { 48312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell newState = getTargetCheckedState(); 48412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 48512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell animateThumbToCheckedState(newState); 48612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } else { 48712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell animateThumbToCheckedState(isChecked()); 48812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 48912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 49012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 49112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private void animateThumbToCheckedState(boolean newCheckedState) { 49212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // TODO animate! 493c3eabb9b6ce7f556313c8e3870d76c5b443f1c51Joe Onorato //float targetPos = newCheckedState ? 0 : getThumbScrollRange(); 494c3eabb9b6ce7f556313c8e3870d76c5b443f1c51Joe Onorato //mThumbPosition = targetPos; 49512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell setChecked(newCheckedState); 49612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 49712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 49812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private boolean getTargetCheckedState() { 49912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return mThumbPosition <= getThumbScrollRange() / 2; 50012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 50112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 50212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 50312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void setChecked(boolean checked) { 50412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.setChecked(checked); 50512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbPosition = checked ? 0 : getThumbScrollRange(); 506c3eabb9b6ce7f556313c8e3870d76c5b443f1c51Joe Onorato invalidate(); 50712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 50812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 50912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 51012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 51112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.onLayout(changed, left, top, right, bottom); 51212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 513c3eabb9b6ce7f556313c8e3870d76c5b443f1c51Joe Onorato mThumbPosition = isChecked() ? 0 : getThumbScrollRange(); 514c3eabb9b6ce7f556313c8e3870d76c5b443f1c51Joe Onorato 51512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchRight = getWidth() - getPaddingRight(); 51612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchLeft = switchRight - mSwitchWidth; 51712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchTop = 0; 51812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchBottom = 0; 51912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) { 52012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell default: 52112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case Gravity.TOP: 52212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchTop = getPaddingTop(); 52312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchBottom = switchTop + mSwitchHeight; 52412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 52512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 52612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case Gravity.CENTER_VERTICAL: 52712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchTop = (getPaddingTop() + getHeight() - getPaddingBottom()) / 2 - 52812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchHeight / 2; 52912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchBottom = switchTop + mSwitchHeight; 53012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 53112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 53212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell case Gravity.BOTTOM: 53312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchBottom = getHeight() - getPaddingBottom(); 53412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchTop = switchBottom - mSwitchHeight; 53512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell break; 53612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 53712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 53812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchLeft = switchLeft; 53912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchTop = switchTop; 54012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchBottom = switchBottom; 54112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mSwitchRight = switchRight; 54212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 54312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 54412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 54512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell protected void onDraw(Canvas canvas) { 54612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.onDraw(canvas); 54712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 54812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Draw the switch 54912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchLeft = mSwitchLeft; 55012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchTop = mSwitchTop; 55112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchRight = mSwitchRight; 55212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchBottom = mSwitchBottom; 55312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 55412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTrackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom); 55512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTrackDrawable.draw(canvas); 55612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 55712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell canvas.save(); 55812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 55912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTrackDrawable.getPadding(mTempRect); 56012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchInnerLeft = switchLeft + mTempRect.left; 56112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchInnerTop = switchTop + mTempRect.top; 56212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchInnerRight = switchRight - mTempRect.right; 56312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int switchInnerBottom = switchBottom - mTempRect.bottom; 56412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom); 56512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 56612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbDrawable.getPadding(mTempRect); 56712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int thumbPos = (int) (mThumbPosition + 0.5f); 56812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int thumbLeft = switchInnerLeft - mTempRect.left + thumbPos; 56912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + mTempRect.right; 57012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 57112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom); 57212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbDrawable.draw(canvas); 57312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 57412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.setColor(mTextColors.getColorForState(getDrawableState(), 57512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextColors.getDefaultColor())); 57612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTextPaint.drawableState = getDrawableState(); 57712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 57812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout; 57912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 58012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell canvas.translate((thumbLeft + thumbRight) / 2 - switchText.getWidth() / 2, 58112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2); 58212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell switchText.draw(canvas); 58312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 58412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell canvas.restore(); 58512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 58612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 58712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 58812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public int getCompoundPaddingRight() { 58912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int padding = super.getCompoundPaddingRight() + mSwitchWidth; 59012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (!TextUtils.isEmpty(getText())) { 59112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell padding += mSwitchPadding; 59212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 59312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return padding; 59412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 59512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 59612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell private int getThumbScrollRange() { 59712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (mTrackDrawable == null) { 59812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return 0; 59912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 60012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTrackDrawable.getPadding(mTempRect); 60112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return mSwitchWidth - mThumbWidth - mTempRect.left - mTempRect.right; 60212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 60312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 60412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 60512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell protected int[] onCreateDrawableState(int extraSpace) { 60612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); 60712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell if (isChecked()) { 60812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mergeDrawableStates(drawableState, CHECKED_STATE_SET); 60912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 61012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return drawableState; 61112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 61212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 61312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 61412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell protected void drawableStateChanged() { 61512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.drawableStateChanged(); 61612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 61712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell int[] myDrawableState = getDrawableState(); 61812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 61912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell // Set the state of the Drawable 62012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbDrawable.setState(myDrawableState); 62112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTrackDrawable.setState(myDrawableState); 62212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 62312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell invalidate(); 62412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 62512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 62612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 62712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell protected boolean verifyDrawable(Drawable who) { 62812190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable; 62912190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 63012190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell 63112190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell @Override 63212190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell public void jumpDrawablesToCurrentState() { 63312190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell super.jumpDrawablesToCurrentState(); 63412190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mThumbDrawable.jumpToCurrentState(); 63512190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell mTrackDrawable.jumpToCurrentState(); 63612190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell } 63712190b36a9da88f8db7dbd9ce16d127d76a904b7Adam Powell} 638