154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project/* 254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * 454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * you may not use this file except in compliance with the License. 654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * You may obtain a copy of the License at 754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * 854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * 1054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * See the License for the specific language governing permissions and 1454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * limitations under the License. 1554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 1654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 1754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectpackage android.widget; 1854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 19911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viveretteimport android.annotation.Nullable; 2054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.content.Context; 21911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viveretteimport android.content.res.ColorStateList; 2254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.content.res.TypedArray; 2354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.graphics.Canvas; 24661e63658da39cccfe49a129e4860455716ff3c9Alan Viveretteimport android.graphics.Insets; 25911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viveretteimport android.graphics.PorterDuff; 2654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.graphics.Rect; 27661e63658da39cccfe49a129e4860455716ff3c9Alan Viveretteimport android.graphics.Region.Op; 2854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.graphics.drawable.Drawable; 29c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanvimport android.os.Bundle; 3054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.util.AttributeSet; 31b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Projectimport android.view.KeyEvent; 3254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.view.MotionEvent; 331029866a12e04e9db52485e2ec0353e764d15549Adam Powellimport android.view.ViewConfiguration; 348a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 358a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 3654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 37911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viveretteimport com.android.internal.R; 38911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 3954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectpublic abstract class AbsSeekBar extends ProgressBar { 40661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette private final Rect mTempRect = new Rect(); 41661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 4254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project private Drawable mThumb; 43a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette private ColorStateList mThumbTintList = null; 44b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette private PorterDuff.Mode mThumbTintMode = null; 45911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette private boolean mHasThumbTint = false; 46b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette private boolean mHasThumbTintMode = false; 47911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 4854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project private int mThumbOffset; 49661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette private boolean mSplitTrack; 50661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 5154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 5254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * On touch, this offset plus the scaled value from the position of the 5354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * touch will form the progress value. Usually 0. 5454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 5554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project float mTouchProgressOffset; 5654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 5754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 5854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Whether this is user seekable. 5954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 6054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project boolean mIsUserSeekable = true; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * On key presses (right or left), the amount to increment/decrement the 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * progress. 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mKeyProgressIncrement = 1; 67661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 6854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project private static final int NO_ALPHA = 0xFF; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private float mDisabledAlpha; 70661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 711029866a12e04e9db52485e2ec0353e764d15549Adam Powell private int mScaledTouchSlop; 721029866a12e04e9db52485e2ec0353e764d15549Adam Powell private float mTouchDownX; 731029866a12e04e9db52485e2ec0353e764d15549Adam Powell private boolean mIsDragging; 741029866a12e04e9db52485e2ec0353e764d15549Adam Powell 7554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public AbsSeekBar(Context context) { 7654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project super(context); 7754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 7854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 7954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public AbsSeekBar(Context context, AttributeSet attrs) { 8054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project super(context, attrs); 8154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 8254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 83617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public AbsSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { 84617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 85617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 86617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 87617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public AbsSeekBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 88617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 8954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 90617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette TypedArray a = context.obtainStyledAttributes( 91617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette attrs, com.android.internal.R.styleable.SeekBar, defStyleAttr, defStyleRes); 92661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 93661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Drawable thumb = a.getDrawable(com.android.internal.R.styleable.SeekBar_thumb); 94661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette setThumb(thumb); 95661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 96b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (a.hasValue(R.styleable.SeekBar_thumbTintMode)) { 97b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mThumbTintMode = Drawable.parseTintMode(a.getInt( 98b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette R.styleable.SeekBar_thumbTintMode, -1), mThumbTintMode); 99b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mHasThumbTintMode = true; 100b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 1014f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette 102911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette if (a.hasValue(R.styleable.SeekBar_thumbTint)) { 103a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mThumbTintList = a.getColorStateList(R.styleable.SeekBar_thumbTint); 104911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mHasThumbTint = true; 105911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 106911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 107661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette // Guess thumb offset if thumb != null, but allow layout to override. 108661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int thumbOffset = a.getDimensionPixelOffset( 109992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy com.android.internal.R.styleable.SeekBar_thumbOffset, getThumbOffset()); 110992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy setThumbOffset(thumbOffset); 111661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 112661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette mSplitTrack = a.getBoolean(com.android.internal.R.styleable.SeekBar_splitTrack, false); 11354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project a.recycle(); 11454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 11554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project a = context.obtainStyledAttributes(attrs, 11654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project com.android.internal.R.styleable.Theme, 0, 0); 11754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mDisabledAlpha = a.getFloat(com.android.internal.R.styleable.Theme_disabledAlpha, 0.5f); 11854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project a.recycle(); 1191029866a12e04e9db52485e2ec0353e764d15549Adam Powell 120b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette applyThumbTint(); 121b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 1221029866a12e04e9db52485e2ec0353e764d15549Adam Powell mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 12354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 12454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 12554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 1268d28c3b3bdab63fab132b81e38d54bc4c132ea8aDaniel Sandler * Sets the thumb that will be drawn at the end of the progress meter within the SeekBar. 1278d28c3b3bdab63fab132b81e38d54bc4c132ea8aDaniel Sandler * <p> 1288d28c3b3bdab63fab132b81e38d54bc4c132ea8aDaniel Sandler * If the thumb is a valid drawable (i.e. not null), half its width will be 1298d28c3b3bdab63fab132b81e38d54bc4c132ea8aDaniel Sandler * used as the new thumb offset (@see #setThumbOffset(int)). 130661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 13154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * @param thumb Drawable representing the thumb 13254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 13354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void setThumb(Drawable thumb) { 134911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette final boolean needUpdate; 1352e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato // This way, calling setThumb again with the same bitmap will result in 1362e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato // it recalcuating mThumbOffset (if for example it the bounds of the 1372e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato // drawable changed) 1382e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato if (mThumb != null && thumb != mThumb) { 1392e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato mThumb.setCallback(null); 1402e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato needUpdate = true; 1412e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato } else { 1422e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato needUpdate = false; 1432e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato } 144911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 14554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (thumb != null) { 14654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project thumb.setCallback(this); 1470af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio if (canResolveLayoutDirection()) { 148e56ffdc7b31b0937628609cc3bbaa15879023569Fabrice Di Meglio thumb.setLayoutDirection(getLayoutDirection()); 1490af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } 1508d28c3b3bdab63fab132b81e38d54bc4c132ea8aDaniel Sandler 1518d28c3b3bdab63fab132b81e38d54bc4c132ea8aDaniel Sandler // Assuming the thumb drawable is symmetric, set the thumb offset 1528d28c3b3bdab63fab132b81e38d54bc4c132ea8aDaniel Sandler // such that the thumb will hang halfway off either edge of the 1538d28c3b3bdab63fab132b81e38d54bc4c132ea8aDaniel Sandler // progress bar. 154992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy mThumbOffset = thumb.getIntrinsicWidth() / 2; 1552e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato 1562e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato // If we're updating get the new states 1572e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato if (needUpdate && 1582e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato (thumb.getIntrinsicWidth() != mThumb.getIntrinsicWidth() 1592e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato || thumb.getIntrinsicHeight() != mThumb.getIntrinsicHeight())) { 1602e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato requestLayout(); 1612e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato } 16254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 163911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 16454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mThumb = thumb; 165911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 166911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette applyThumbTint(); 16754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project invalidate(); 168911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 1692e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato if (needUpdate) { 170661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette updateThumbAndTrackPos(getWidth(), getHeight()); 1710283a5573c0a8b239f88147fe4ecf1b379e2f0a4Adam Powell if (thumb != null && thumb.isStateful()) { 1722e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato // Note that if the states are different this won't work. 1732e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato // For now, let's consider that an app bug. 1742e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato int[] state = getDrawableState(); 1752e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato thumb.setState(state); 1762e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato } 1772e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato } 17854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 17954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 18054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 1813004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell * Return the drawable used to represent the scroll thumb - the component that 1823004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell * the user can drag back and forth indicating the current value by its position. 1833004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell * 1843004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell * @return The current thumb drawable 1853004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell */ 1863004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell public Drawable getThumb() { 1873004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell return mThumb; 1883004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell } 1893004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell 1903004cc50f22e724efb791aa80e9d6c566d2ddb5dAdam Powell /** 1914f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * Applies a tint to the thumb drawable. Does not modify the current tint 192b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 193911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * <p> 194911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * Subsequent calls to {@link #setThumb(Drawable)} will automatically 195911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * mutate the drawable and apply the specified tint and tint mode using 196a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * {@link Drawable#setTintList(ColorStateList)}. 197911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 198911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @param tint the tint to apply, may be {@code null} to clear tint 199911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 200911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#SeekBar_thumbTint 201a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see #getThumbTintList() 202a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see Drawable#setTintList(ColorStateList) 203911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 204a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setThumbTintList(@Nullable ColorStateList tint) { 205a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mThumbTintList = tint; 206911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mHasThumbTint = true; 207911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 208911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette applyThumbTint(); 209911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 210911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 211911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 212b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * Returns the tint applied to the thumb drawable, if specified. 213b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * 214911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @return the tint applied to the thumb drawable 215911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#SeekBar_thumbTint 216a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see #setThumbTintList(ColorStateList) 217911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 218911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette @Nullable 219a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public ColorStateList getThumbTintList() { 220a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette return mThumbTintList; 221911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 222911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 223911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 224911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * Specifies the blending mode used to apply the tint specified by 225a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * {@link #setThumbTintList(ColorStateList)}} to the thumb drawable. The 226b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * default mode is {@link PorterDuff.Mode#SRC_IN}. 227911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * 228911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @param tintMode the blending mode used to apply the tint, may be 229911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * {@code null} to clear tint 2304f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * 231911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#SeekBar_thumbTintMode 2324f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @see #getThumbTintMode() 233a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette * @see Drawable#setTintMode(PorterDuff.Mode) 234911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 235911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette public void setThumbTintMode(@Nullable PorterDuff.Mode tintMode) { 2364f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette mThumbTintMode = tintMode; 237b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mHasThumbTintMode = true; 2384f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette 2394f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette applyThumbTint(); 240911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 241911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 242911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 243b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * Returns the blending mode used to apply the tint to the thumb drawable, 244b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * if specified. 245b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette * 246911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @return the blending mode used to apply the tint to the thumb drawable 247911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette * @attr ref android.R.styleable#SeekBar_thumbTintMode 2484f64c048505a432e549ccb756634ecebf28f9e80Alan Viverette * @see #setThumbTintMode(PorterDuff.Mode) 249911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette */ 250911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette @Nullable 251911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette public PorterDuff.Mode getThumbTintMode() { 252911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette return mThumbTintMode; 253911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 254911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 255911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette private void applyThumbTint() { 256b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mThumb != null && (mHasThumbTint || mHasThumbTintMode)) { 257911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette mThumb = mThumb.mutate(); 258b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 259b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mHasThumbTint) { 260b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mThumb.setTintList(mThumbTintList); 261b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 262b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette 263b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette if (mHasThumbTintMode) { 264b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette mThumb.setTintMode(mThumbTintMode); 265b56f5d2ab18f881eb075b698e9ce1b4a4a09ff64Alan Viverette } 266d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette 267d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette // The drawable (or one of its children) may not have been 268d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette // stateful before applying the tint, so let's try again. 269d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette if (mThumb.isStateful()) { 270d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette mThumb.setState(getDrawableState()); 271d5133792391443521dc15f7da7de5d280e6703ddAlan Viverette } 272911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 273911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette } 274911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette 275911743652b597057a1bd7ef8a921e9ff8dce0f4aAlan Viverette /** 27654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * @see #setThumbOffset(int) 27754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 27854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public int getThumbOffset() { 27954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return mThumbOffset; 28054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 28154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 28254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 28354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Sets the thumb offset that allows the thumb to extend out of the range of 28454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * the track. 285661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 28654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * @param thumbOffset The offset amount in pixels. 28754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 28854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void setThumbOffset(int thumbOffset) { 28954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mThumbOffset = thumbOffset; 29054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project invalidate(); 29154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 29254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 294661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * Specifies whether the track should be split by the thumb. When true, 295661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * the thumb's optical bounds will be clipped out of the track drawable, 296661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * then the thumb will be drawn into the resulting gap. 297661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 298661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * @param splitTrack Whether the track should be split by the thumb 299661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette */ 300661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette public void setSplitTrack(boolean splitTrack) { 301661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette mSplitTrack = splitTrack; 302661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette invalidate(); 303661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 304661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 305661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette /** 306661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * Returns whether the track should be split by the thumb. 307661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette */ 308661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette public boolean getSplitTrack() { 309661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette return mSplitTrack; 310661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 311661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 312661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette /** 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the amount of progress changed via the arrow keys. 314661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param increment The amount to increment or decrement when the user 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * presses the arrow keys. 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setKeyProgressIncrement(int increment) { 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeyProgressIncrement = increment < 0 ? -increment : increment; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the amount of progress changed via the arrow keys. 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * By default, this will be a value that is derived from the max progress. 326661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The amount to increment or decrement when the user presses the 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * arrow keys. This will be positive. 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getKeyProgressIncrement() { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mKeyProgressIncrement; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 333661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized void setMax(int max) { 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setMax(max); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mKeyProgressIncrement == 0) || (getMax() / mKeyProgressIncrement > 20)) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It will take the user too long to change this via keys, change it 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to something more reasonable 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setKeyProgressIncrement(Math.max(1, Math.round((float) getMax() / 20))); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 34654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected boolean verifyDrawable(Drawable who) { 34754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return who == mThumb || super.verifyDrawable(who); 34854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 34954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 35054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 351e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn public void jumpDrawablesToCurrentState() { 352e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn super.jumpDrawablesToCurrentState(); 3538de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette 3548de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette if (mThumb != null) { 3558de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette mThumb.jumpToCurrentState(); 3568de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette } 357e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn } 358e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn 359e213677037f836529efcc0ac201fc61dd95481c5Dianne Hackborn @Override 36054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected void drawableStateChanged() { 36154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project super.drawableStateChanged(); 362661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 363661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Drawable progressDrawable = getProgressDrawable(); 36454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (progressDrawable != null) { 36554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project progressDrawable.setAlpha(isEnabled() ? NO_ALPHA : (int) (NO_ALPHA * mDisabledAlpha)); 36654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 367661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 368661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Drawable thumb = mThumb; 369661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette if (thumb != null && thumb.isStateful()) { 370661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette thumb.setState(getDrawableState()); 371b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Project } 37254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 373661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 374cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette @Override 3758de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette public void drawableHotspotChanged(float x, float y) { 3768de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette super.drawableHotspotChanged(x, y); 377cebc6bab51d9c77db8f346c1390169eabac4f27dAlan Viverette 3788de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette if (mThumb != null) { 3798de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette mThumb.setHotspot(x, y); 3802356c5e69b0911e6334ebf6374217898371be5acAlan Viverette } 3812356c5e69b0911e6334ebf6374217898371be5acAlan Viverette } 3822356c5e69b0911e6334ebf6374217898371be5acAlan Viverette 3832356c5e69b0911e6334ebf6374217898371be5acAlan Viverette @Override 3846518ad760f98a0aa5db8c49ce1564bf5907a2c15Svetoslav Ganov void onProgressRefresh(float scale, boolean fromUser) { 3856518ad760f98a0aa5db8c49ce1564bf5907a2c15Svetoslav Ganov super.onProgressRefresh(scale, fromUser); 386661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 3875ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette final Drawable thumb = mThumb; 3885ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette if (thumb != null) { 3895ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE); 390661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 3915ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette // Since we draw translated, the drawable's bounds that it signals 3925ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette // for invalidation won't be the actual bounds we want invalidated, 3935ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette // so just invalidate this whole view. 3945ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette invalidate(); 3955ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette } 3960c11a489075e05ae84d3c8b5d7ac1ae293af00f9Jon Miranda } 3970c11a489075e05ae84d3c8b5d7ac1ae293af00f9Jon Miranda 3980c11a489075e05ae84d3c8b5d7ac1ae293af00f9Jon Miranda @Override 39954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected void onSizeChanged(int w, int h, int oldw, int oldh) { 400f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio super.onSizeChanged(w, h, oldw, oldh); 401661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 402661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette updateThumbAndTrackPos(w, h); 4032e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato } 4042e585f7e22efef11dc6af36acfbf1c3040d6a511Joe Onorato 405661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette private void updateThumbAndTrackPos(int w, int h) { 406661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Drawable track = getCurrentDrawable(); 407661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Drawable thumb = mThumb; 408661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 40954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // The max height does not incorporate padding, whereas the height 410661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette // parameter does. 411661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int trackHeight = Math.min(mMaxHeight, h - mPaddingTop - mPaddingBottom); 412661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int thumbHeight = thumb == null ? 0 : thumb.getIntrinsicHeight(); 413661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 414661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette // Apply offset to whichever item is taller. 415661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int trackOffset; 416661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int thumbOffset; 41754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (thumbHeight > trackHeight) { 418661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette trackOffset = (thumbHeight - trackHeight) / 2; 419661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette thumbOffset = 0; 42054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } else { 421661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette trackOffset = 0; 422661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette thumbOffset = (trackHeight - thumbHeight) / 2; 423661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 424661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 425661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette if (track != null) { 426661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette track.setBounds(0, trackOffset, w - mPaddingRight - mPaddingLeft, 427661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette h - mPaddingBottom - trackOffset - mPaddingTop); 428661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 429661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 430661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette if (thumb != null) { 431661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette setThumbPos(w, thumb, getScale(), thumbOffset); 43254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 43354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 43454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 435661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette private float getScale() { 436661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int max = getMax(); 437661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette return max > 0 ? getProgress() / (float) max : 0; 438661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 439661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 44054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 441661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * Updates the thumb drawable bounds. 442661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * 443661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * @param w Width of the view, including padding 444661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * @param thumb Drawable used for the thumb 445661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * @param scale Current progress between 0 and 1 446661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * @param offset Vertical offset for centering. If set to 447661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * {@link Integer#MIN_VALUE}, the current offset will be used. 44854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 449661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette private void setThumbPos(int w, Drawable thumb, float scale, int offset) { 45054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int available = w - mPaddingLeft - mPaddingRight; 45161956606818918194a38e045a8e35e7108480e5eAlan Viverette final int thumbWidth = thumb.getIntrinsicWidth(); 45261956606818918194a38e045a8e35e7108480e5eAlan Viverette final int thumbHeight = thumb.getIntrinsicHeight(); 45354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project available -= thumbWidth; 45454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 45554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // The extra space for the thumb to move on the track 45654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project available += mThumbOffset * 2; 45754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 45861956606818918194a38e045a8e35e7108480e5eAlan Viverette final int thumbPos = (int) (scale * available + 0.5f); 45954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 46061956606818918194a38e045a8e35e7108480e5eAlan Viverette final int top, bottom; 461661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette if (offset == Integer.MIN_VALUE) { 46261956606818918194a38e045a8e35e7108480e5eAlan Viverette final Rect oldBounds = thumb.getBounds(); 46361956606818918194a38e045a8e35e7108480e5eAlan Viverette top = oldBounds.top; 46461956606818918194a38e045a8e35e7108480e5eAlan Viverette bottom = oldBounds.bottom; 46554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } else { 466661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette top = offset; 467661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette bottom = offset + thumbHeight; 46854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 46961956606818918194a38e045a8e35e7108480e5eAlan Viverette 4702b378cde411b551464f0040e935692073cfb119fFabrice Di Meglio final int left = (isLayoutRtl() && mMirrorForRtl) ? available - thumbPos : thumbPos; 47161956606818918194a38e045a8e35e7108480e5eAlan Viverette final int right = left + thumbWidth; 47261956606818918194a38e045a8e35e7108480e5eAlan Viverette 47361956606818918194a38e045a8e35e7108480e5eAlan Viverette final Drawable background = getBackground(); 474c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette if (background != null) { 4758de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette final Rect bounds = thumb.getBounds(); 47661956606818918194a38e045a8e35e7108480e5eAlan Viverette final int offsetX = mPaddingLeft - mThumbOffset; 47761956606818918194a38e045a8e35e7108480e5eAlan Viverette final int offsetY = mPaddingTop; 478304624100b363137913d1d910690fc83872e41c3Alan Viverette background.setHotspotBounds(left + offsetX, top + offsetY, 479304624100b363137913d1d910690fc83872e41c3Alan Viverette right + offsetX, bottom + offsetY); 48061956606818918194a38e045a8e35e7108480e5eAlan Viverette } 48161956606818918194a38e045a8e35e7108480e5eAlan Viverette 48261956606818918194a38e045a8e35e7108480e5eAlan Viverette // Canvas will be translated, so 0,0 is where we start drawing 48361956606818918194a38e045a8e35e7108480e5eAlan Viverette thumb.setBounds(left, top, right, bottom); 48454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 4850af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio 4864457e85a7090ad51726d50a4daf981d917cceeddFabrice Di Meglio /** 4874457e85a7090ad51726d50a4daf981d917cceeddFabrice Di Meglio * @hide 4884457e85a7090ad51726d50a4daf981d917cceeddFabrice Di Meglio */ 4890af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio @Override 4900af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio public void onResolveDrawables(int layoutDirection) { 4910af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio super.onResolveDrawables(layoutDirection); 4920af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio 4930af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio if (mThumb != null) { 4940af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio mThumb.setLayoutDirection(layoutDirection); 4950af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } 4960af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } 4970af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio 49854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 49954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected synchronized void onDraw(Canvas canvas) { 50054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project super.onDraw(canvas); 501661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette drawThumb(canvas); 5028de1494557cf1d00c1c3fce439138a28de7fbd61Alan Viverette 503661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 504661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 505661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette @Override 506661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette void drawTrack(Canvas canvas) { 507661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Drawable thumbDrawable = mThumb; 508661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette if (thumbDrawable != null && mSplitTrack) { 509661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Insets insets = thumbDrawable.getOpticalInsets(); 510661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Rect tempRect = mTempRect; 511661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette thumbDrawable.copyBounds(tempRect); 512661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette tempRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop); 513661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette tempRect.left += insets.left; 514661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette tempRect.right -= insets.right; 515661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 516661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final int saveCount = canvas.save(); 517661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette canvas.clipRect(tempRect, Op.DIFFERENCE); 518661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette super.drawTrack(canvas); 519661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette canvas.restoreToCount(saveCount); 520661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } else { 521661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette super.drawTrack(canvas); 522661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 523661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette } 524661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 525661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette /** 526661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette * Draw the thumb. 527661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette */ 528661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette void drawThumb(Canvas canvas) { 52954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (mThumb != null) { 53054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project canvas.save(); 53154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // Translate the padding. For the x, we need to allow the thumb to 53254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // draw in its extra space 53354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project canvas.translate(mPaddingLeft - mThumbOffset, mPaddingTop); 53454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mThumb.draw(canvas); 53554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project canvas.restore(); 53654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 53754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 53854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 53954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 54054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 54154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project Drawable d = getCurrentDrawable(); 54254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 54354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int thumbHeight = mThumb == null ? 0 : mThumb.getIntrinsicHeight(); 54454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int dw = 0; 54554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int dh = 0; 54654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (d != null) { 54754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth())); 54854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight())); 54954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project dh = Math.max(thumbHeight, dh); 55054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 55154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project dw += mPaddingLeft + mPaddingRight; 55254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project dh += mPaddingTop + mPaddingBottom; 553661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 554189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn setMeasuredDimension(resolveSizeAndState(dw, widthMeasureSpec, 0), 555189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn resolveSizeAndState(dh, heightMeasureSpec, 0)); 55654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 557661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 55854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 55954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public boolean onTouchEvent(MotionEvent event) { 56054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (!mIsUserSeekable || !isEnabled()) { 56154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return false; 56254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 563661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 56454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project switch (event.getAction()) { 56554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project case MotionEvent.ACTION_DOWN: 5661029866a12e04e9db52485e2ec0353e764d15549Adam Powell if (isInScrollingContainer()) { 5671029866a12e04e9db52485e2ec0353e764d15549Adam Powell mTouchDownX = event.getX(); 5681029866a12e04e9db52485e2ec0353e764d15549Adam Powell } else { 5691029866a12e04e9db52485e2ec0353e764d15549Adam Powell setPressed(true); 5702c5b8cc71bc8ac1efa944568c1292929073bbc36Adam Powell if (mThumb != null) { 5712c5b8cc71bc8ac1efa944568c1292929073bbc36Adam Powell invalidate(mThumb.getBounds()); // This may be within the padding region 5722c5b8cc71bc8ac1efa944568c1292929073bbc36Adam Powell } 5731029866a12e04e9db52485e2ec0353e764d15549Adam Powell onStartTrackingTouch(); 5741029866a12e04e9db52485e2ec0353e764d15549Adam Powell trackTouchEvent(event); 5751029866a12e04e9db52485e2ec0353e764d15549Adam Powell attemptClaimDrag(); 5761029866a12e04e9db52485e2ec0353e764d15549Adam Powell } 57754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project break; 578661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 57954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project case MotionEvent.ACTION_MOVE: 5801029866a12e04e9db52485e2ec0353e764d15549Adam Powell if (mIsDragging) { 5811029866a12e04e9db52485e2ec0353e764d15549Adam Powell trackTouchEvent(event); 5821029866a12e04e9db52485e2ec0353e764d15549Adam Powell } else { 5831029866a12e04e9db52485e2ec0353e764d15549Adam Powell final float x = event.getX(); 5841029866a12e04e9db52485e2ec0353e764d15549Adam Powell if (Math.abs(x - mTouchDownX) > mScaledTouchSlop) { 5851029866a12e04e9db52485e2ec0353e764d15549Adam Powell setPressed(true); 5862c5b8cc71bc8ac1efa944568c1292929073bbc36Adam Powell if (mThumb != null) { 5872c5b8cc71bc8ac1efa944568c1292929073bbc36Adam Powell invalidate(mThumb.getBounds()); // This may be within the padding region 5882c5b8cc71bc8ac1efa944568c1292929073bbc36Adam Powell } 5891029866a12e04e9db52485e2ec0353e764d15549Adam Powell onStartTrackingTouch(); 5901029866a12e04e9db52485e2ec0353e764d15549Adam Powell trackTouchEvent(event); 5911029866a12e04e9db52485e2ec0353e764d15549Adam Powell attemptClaimDrag(); 5921029866a12e04e9db52485e2ec0353e764d15549Adam Powell } 5931029866a12e04e9db52485e2ec0353e764d15549Adam Powell } 59454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project break; 595661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 59654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project case MotionEvent.ACTION_UP: 5971029866a12e04e9db52485e2ec0353e764d15549Adam Powell if (mIsDragging) { 5981029866a12e04e9db52485e2ec0353e764d15549Adam Powell trackTouchEvent(event); 5991029866a12e04e9db52485e2ec0353e764d15549Adam Powell onStopTrackingTouch(); 6001029866a12e04e9db52485e2ec0353e764d15549Adam Powell setPressed(false); 6011029866a12e04e9db52485e2ec0353e764d15549Adam Powell } else { 6021029866a12e04e9db52485e2ec0353e764d15549Adam Powell // Touch up when we never crossed the touch slop threshold should 6031029866a12e04e9db52485e2ec0353e764d15549Adam Powell // be interpreted as a tap-seek to that location. 6041029866a12e04e9db52485e2ec0353e764d15549Adam Powell onStartTrackingTouch(); 6051029866a12e04e9db52485e2ec0353e764d15549Adam Powell trackTouchEvent(event); 6061029866a12e04e9db52485e2ec0353e764d15549Adam Powell onStopTrackingTouch(); 6071029866a12e04e9db52485e2ec0353e764d15549Adam Powell } 608eb9fdc21b14368b2f8c71939eb063ddcee8c28a2Daniel Sandler // ProgressBar doesn't know to repaint the thumb drawable 609eb9fdc21b14368b2f8c71939eb063ddcee8c28a2Daniel Sandler // in its inactive state when the touch stops (because the 610eb9fdc21b14368b2f8c71939eb063ddcee8c28a2Daniel Sandler // value has not apparently changed) 611eb9fdc21b14368b2f8c71939eb063ddcee8c28a2Daniel Sandler invalidate(); 61254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project break; 613661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 61454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project case MotionEvent.ACTION_CANCEL: 6151029866a12e04e9db52485e2ec0353e764d15549Adam Powell if (mIsDragging) { 6161029866a12e04e9db52485e2ec0353e764d15549Adam Powell onStopTrackingTouch(); 6171029866a12e04e9db52485e2ec0353e764d15549Adam Powell setPressed(false); 6181029866a12e04e9db52485e2ec0353e764d15549Adam Powell } 619eb9fdc21b14368b2f8c71939eb063ddcee8c28a2Daniel Sandler invalidate(); // see above explanation 62054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project break; 62154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 62254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return true; 62354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 62454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 625c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette private void setHotspot(float x, float y) { 62661956606818918194a38e045a8e35e7108480e5eAlan Viverette final Drawable bg = getBackground(); 627c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette if (bg != null) { 628c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette bg.setHotspot(x, y); 62961956606818918194a38e045a8e35e7108480e5eAlan Viverette } 63061956606818918194a38e045a8e35e7108480e5eAlan Viverette } 63161956606818918194a38e045a8e35e7108480e5eAlan Viverette 63254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project private void trackTouchEvent(MotionEvent event) { 63354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project final int width = getWidth(); 63454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project final int available = width - mPaddingLeft - mPaddingRight; 63561956606818918194a38e045a8e35e7108480e5eAlan Viverette final int x = (int) event.getX(); 63654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project float scale; 63754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project float progress = 0; 6382b378cde411b551464f0040e935692073cfb119fFabrice Di Meglio if (isLayoutRtl() && mMirrorForRtl) { 6390af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio if (x > width - mPaddingRight) { 6400af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio scale = 0.0f; 6410af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } else if (x < mPaddingLeft) { 6420af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio scale = 1.0f; 6430af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } else { 6440af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio scale = (float)(available - x + mPaddingLeft) / (float)available; 6450af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio progress = mTouchProgressOffset; 6460af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } 64754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } else { 6480af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio if (x < mPaddingLeft) { 6490af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio scale = 0.0f; 6500af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } else if (x > width - mPaddingRight) { 6510af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio scale = 1.0f; 6520af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } else { 6530af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio scale = (float)(x - mPaddingLeft) / (float)available; 6540af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio progress = mTouchProgressOffset; 6550af4b8b0c8b038bca9b4f60eb81f71e186f471ceFabrice Di Meglio } 65654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 65769577ae794751e6ecaca6a580b1b33545bd21082Jean-Baptiste Queru final int max = getMax(); 65854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project progress += scale * max; 65961956606818918194a38e045a8e35e7108480e5eAlan Viverette 660c80ad99a33ee49d0bac994c1749ff24d243c3862Alan Viverette setHotspot(x, (int) event.getY()); 66154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project setProgress((int) progress, true); 66254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 663f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project 664f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project /** 665f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project * Tries to claim the user's drag motion, and requests disallowing any 666f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project * ancestors from stealing events in the drag. 667f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project */ 668f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project private void attemptClaimDrag() { 669f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project if (mParent != null) { 670f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project mParent.requestDisallowInterceptTouchEvent(true); 671f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project } 672f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project } 673661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 67454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 67554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * This is called when the user has started touching this widget. 67654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 67754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project void onStartTrackingTouch() { 6781029866a12e04e9db52485e2ec0353e764d15549Adam Powell mIsDragging = true; 67954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 68054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 68154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 68254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * This is called when the user either releases his touch or the touch is 68354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * canceled. 68454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 68554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project void onStopTrackingTouch() { 6861029866a12e04e9db52485e2ec0353e764d15549Adam Powell mIsDragging = false; 68754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 68854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 689105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** 690105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project * Called when the user changes the seekbar's progress by using a key event. 691105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project */ 692105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project void onKeyChange() { 693105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 694105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 695b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Project @Override 696b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 697992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy if (isEnabled()) { 698992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy int progress = getProgress(); 699992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy switch (keyCode) { 700992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy case KeyEvent.KEYCODE_DPAD_LEFT: 701992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy if (progress <= 0) break; 7025ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette setProgress(progress - mKeyProgressIncrement, true); 703992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy onKeyChange(); 704992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy return true; 705661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 706992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy case KeyEvent.KEYCODE_DPAD_RIGHT: 707992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy if (progress >= getMax()) break; 7085ce0ec0efd541362359bfead8e62ade80a0425caAlan Viverette setProgress(progress + mKeyProgressIncrement, true); 709992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy onKeyChange(); 710992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy return true; 711992cc4282e92c0b7c192247261c54933acab5ad0Romain Guy } 712b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Project } 713b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Project 714b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Project return super.onKeyDown(keyCode, event); 715b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Project } 716b798689749c64baba81f02e10cf2157c747d6b46The Android Open Source Project 7178a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 7188a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 7198a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityEvent(event); 7208a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov event.setClassName(AbsSeekBar.class.getName()); 7218a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 7228a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 7238a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 7248a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 7258a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityNodeInfo(info); 7268a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov info.setClassName(AbsSeekBar.class.getName()); 727c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv 728c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv if (isEnabled()) { 729c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv final int progress = getProgress(); 730c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv if (progress > 0) { 731c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); 732c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 733c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv if (progress < getMax()) { 734c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); 735c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 736c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 737c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 738c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv 739c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv @Override 740c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv public boolean performAccessibilityAction(int action, Bundle arguments) { 741c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv if (super.performAccessibilityAction(action, arguments)) { 742c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv return true; 743c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 744c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv if (!isEnabled()) { 745c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv return false; 746c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 747c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv final int progress = getProgress(); 748c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv final int increment = Math.max(1, Math.round((float) getMax() / 5)); 749c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv switch (action) { 750c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { 751c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv if (progress <= 0) { 752c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv return false; 753c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 754c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv setProgress(progress - increment, true); 755c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv onKeyChange(); 756c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv return true; 757c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 758c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { 759c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv if (progress >= getMax()) { 760c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv return false; 761c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 762c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv setProgress(progress + increment, true); 763c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv onKeyChange(); 764c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv return true; 765c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 766c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv } 767c826b7d8fa330970d1ab29fd3b2790a5bc01e26calanv return false; 7688a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 769f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio 770f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio @Override 771f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio public void onRtlPropertiesChanged(int layoutDirection) { 772f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio super.onRtlPropertiesChanged(layoutDirection); 773f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio 774661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette final Drawable thumb = mThumb; 775f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio if (thumb != null) { 776661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette setThumbPos(getWidth(), thumb, getScale(), Integer.MIN_VALUE); 777661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette 778661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette // Since we draw translated, the drawable's bounds that it signals 779661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette // for invalidation won't be the actual bounds we want invalidated, 780661e63658da39cccfe49a129e4860455716ff3c9Alan Viverette // so just invalidate this whole view. 781f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio invalidate(); 782f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio } 783f37df1b6c23316e3050a399f9218087c4000564aFabrice Di Meglio } 78454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project} 785