NumberPicker.java revision 01fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978af
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrookpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 198bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powellimport com.android.internal.R; 208bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powell 21206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.animation.Animator; 22206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.animation.AnimatorListenerAdapter; 23206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.animation.AnimatorSet; 24206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.animation.ObjectAnimator; 25206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.animation.ValueAnimator; 2668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrookimport android.annotation.Widget; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 28206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.content.res.ColorStateList; 29206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.content.res.TypedArray; 30206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.graphics.Canvas; 31206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.graphics.Color; 32206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.graphics.Paint; 3350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganovimport android.graphics.Rect; 34e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganovimport android.graphics.Paint.Align; 359cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganovimport android.graphics.drawable.Drawable; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputFilter; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputType; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Spanned; 39206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.text.TextUtils; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.method.NumberKeyListener; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 42206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.util.SparseArray; 439cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganovimport android.util.TypedValue; 44206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.KeyEvent; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 46206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.MotionEvent; 47206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.VelocityTracker; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 49206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.ViewConfiguration; 50e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganovimport android.view.LayoutInflater.Filter; 519cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganovimport android.view.animation.DecelerateInterpolator; 52206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.inputmethod.InputMethodManager; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook/** 554bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * A widget that enables the user to select a number form a predefined range. 564bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * The widget presents an input filed and up and down buttons for selecting the 574bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * current value. Pressing/long pressing the up and down buttons increments and 584bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * decrements the current value respectively. Touching the input filed shows a 594bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * scroll wheel, tapping on which while shown and not moving allows direct edit 604bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * of the current value. Sliding motions up or down hide the buttons and the 614bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * input filed, show the scroll wheel, and rotate the latter. Flinging is 624bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * also supported. The widget enables mapping from positions to strings such 634bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * that instead the position index the corresponding string is displayed. 644bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 654bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * For an example of using this widget, see {@link android.widget.TimePicker}. 664bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 6768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 6868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook@Widget 6968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrookpublic class NumberPicker extends LinearLayout { 70fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 7168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 72e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * The default update interval during long press. 73e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 74e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private static final long DEFAULT_LONG_PRESS_UPDATE_INTERVAL = 300; 75e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 76e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 77206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The index of the middle selector item. 7868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 79206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_MIDDLE_ITEM_INDEX = 2; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 82206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The coefficient by which to adjust (divide) the max fling velocity. 8368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 84206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT = 8; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 86206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 87206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The the duration for adjusting the selector wheel. 88206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 89206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_ADJUSTMENT_DURATION_MILLIS = 800; 90fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 91206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 92206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The the delay for showing the input controls after a single tap on the 93206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * input text. 94206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 95206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SHOW_INPUT_CONTROLS_DELAY_MILLIS = ViewConfiguration 96206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov .getDoubleTapTimeout(); 97206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 98206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 99206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The update step for incrementing the current value. 100206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 101206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int UPDATE_STEP_INCREMENT = 1; 102206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 103206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 104206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The update step for decrementing the current value. 105206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 106206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int UPDATE_STEP_DECREMENT = -1; 107206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 108206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 109206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The strength of fading in the top and bottom while drawing the selector. 110206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 111206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final float TOP_AND_BOTTOM_FADING_EDGE_STRENGTH = 0.9f; 112206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 113206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1149cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * The default unscaled height of the selection divider. 1159cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 1169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final int UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT = 2; 1179cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 1189cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 119206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The numbers accepted by the input text's {@link Filter} 120206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 121206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final char[] DIGIT_CHARACTERS = new char[] { 122206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 123206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 124206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 125206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 126206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Use a custom NumberPicker formatting callback to use two-digit minutes 127206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * strings like "01". Keeping a static formatter etc. is the most efficient 128206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * way to do this; it avoids creating temporary objects on every call to 129206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * format(). 130e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 131e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @hide 132206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 133206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() { 134206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final StringBuilder mBuilder = new StringBuilder(); 135206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 136f0ef665299d795df7905897e1c337e37891dafefJean-Baptiste Queru final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US); 137206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 138206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final Object[] mArgs = new Object[1]; 139206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 140e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String format(int value) { 141206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mArgs[0] = value; 142206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBuilder.delete(0, mBuilder.length()); 143206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mFmt.format("%02d", mArgs); 144206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mFmt.toString(); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 148206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 149206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The increment button. 150206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 151206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final ImageButton mIncrementButton; 152206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 153206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 154206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The decrement button. 155206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 156206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final ImageButton mDecrementButton; 157206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 158206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 159206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The text for showing the current value. 160206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 161206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final EditText mInputText; 162206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 163206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 164206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The height of the text. 165206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 166206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int mTextSize; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 168206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 169206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The values to be displayed instead the indices. 170206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] mDisplayedValues; 17268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 17368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 17468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Lower value of the range of numbers allowed for the NumberPicker 17568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 176e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mMinValue; 17768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 17868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 17968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Upper value of the range of numbers allowed for the NumberPicker 18068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 181e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mMaxValue; 18268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 18368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 18468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Current value of this NumberPicker 18568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 186e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mValue; 18768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 18868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 189206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Listener to be notified upon current value change. 19068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 191cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov private OnValueChangeListener mOnValueChangeListener; 19250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 19350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 19450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * Listener to be notified upon scroll state change. 19550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 19650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov private OnScrollListener mOnScrollListener; 197206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 198206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 199206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Formatter for for displaying the current value. 200206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Formatter mFormatter; 202fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 203206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 204206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The speed for updating the value form long press. 205206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 206e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private long mLongPressUpdateInterval = DEFAULT_LONG_PRESS_UPDATE_INTERVAL; 207fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 20868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 209206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Cache for the string representation of selector indices. 210206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 211206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final SparseArray<String> mSelectorIndexToStringCache = new SparseArray<String>(); 212206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 213206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 214206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The selector indices whose value are show by the selector. 215206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 216206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int[] mSelectorIndices = new int[] { 217206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, 218206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Integer.MIN_VALUE 219206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 220206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 221206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 222206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Paint} for drawing the selector. 223206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 224206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Paint mSelectorPaint; 225206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 226206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 227206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The height of a selector element (text + gap). 228206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 229206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectorElementHeight; 230206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 231206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 232206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The initial offset of the scroll selector. 233206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 234206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mInitialScrollOffset = Integer.MIN_VALUE; 235206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 236206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 237206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The current offset of the scroll selector. 238206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 239206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mCurrentScrollOffset; 240206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 241206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 242206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Scroller} responsible for flinging the selector. 243206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 244206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Scroller mFlingScroller; 245206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 246206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 247206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Scroller} responsible for adjusting the selector. 248206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 249206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Scroller mAdjustScroller; 250206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 251206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 252206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The previous Y coordinate while scrolling the selector. 253206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 254206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mPreviousScrollerY; 255206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 256206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 257206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for setting the input text selection. 258206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 259206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private SetSelectionCommand mSetSelectionCommand; 260206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 261206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 262206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for adjusting the scroller. 263206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 264206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private AdjustScrollerCommand mAdjustScrollerCommand; 265206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 266206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 267206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for updating the current value from long 268206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * press. 269206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 270206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private UpdateValueFromLongPressCommand mUpdateFromLongPressCommand; 271206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 272206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 273206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * {@link Animator} for showing the up/down arrows. 274206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 275206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final AnimatorSet mShowInputControlsAnimator; 276206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 277206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 278206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The Y position of the last down event. 279206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 280206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private float mLastDownEventY; 281206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 282206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 283206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The Y position of the last motion event. 284206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 285206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private float mLastMotionEventY; 286206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 287206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 288206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to begin edit on next up event. 289206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 290206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mBeginEditOnUpEvent; 291206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 292206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 293206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to adjust the selector wheel on next up event. 294206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 295206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mAdjustScrollerOnUpEvent; 296206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 297206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 298206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to draw the selector wheel. 299206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 300206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mDrawSelectorWheel; 301206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 302206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 303206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Determines speed during touch scrolling. 304206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 305206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private VelocityTracker mVelocityTracker; 306206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 307206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 308206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledTouchSlop() 309206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 310206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mTouchSlop; 311206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 312206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 313206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledMinimumFlingVelocity() 314206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 315206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mMinimumFlingVelocity; 316206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 317206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 318206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledMaximumFlingVelocity() 319206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 320206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mMaximumFlingVelocity; 321206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 322206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 323206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag whether the selector should wrap around. 324206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 325e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private boolean mWrapSelectorWheel; 326206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 327206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 328206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The back ground color used to optimize scroller fading. 32968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 330206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int mSolidColor; 331206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 332206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 3334243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * Flag indicating if this widget supports flinging. 3344243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov */ 3354243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov private final boolean mFlingable; 3364243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 3374243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov /** 3389cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * Divider for showing item to be selected while scrolling 3399cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 3409cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final Drawable mSelectionDivider; 3419cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 3429cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 3439cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * The height of the selection divider. 3449cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 3459cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final int mSelectionDividerHeight; 3469cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 3479cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 348206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Reusable {@link Rect} instance. 349206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 350206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Rect mTempRect = new Rect(); 351206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 352206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 35350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The current scroll state of the number picker. 35450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 35550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE; 35650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 35750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 3589cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * The duration of the animation for showing the input controls. 3599cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 3609cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final long mShowInputControlsAnimimationDuration; 3619cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 3629cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 363e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface to listen for changes of the current value. 364206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 365cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov public interface OnValueChangeListener { 366e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 367206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 3684bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Called upon a change of the current value. 3694bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 370206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param picker The NumberPicker associated with this listener. 371206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param oldVal The previous value. 372206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param newVal The new value. 373206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 374e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov void onValueChange(NumberPicker picker, int oldVal, int newVal); 375206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 376206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 377206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 378e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface to listen for the picker scroll state. 37950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 38050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public interface OnScrollListener { 38150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 38250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 38350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The view is not scrolling. 38450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 38550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_IDLE = 0; 38650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 38750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 38850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The user is scrolling using touch, and their finger is still on the screen. 38950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 39050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_TOUCH_SCROLL = 1; 39150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 39250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 39350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The user had previously been scrolling using touch and performed a fling. 39450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 39550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_FLING = 2; 39650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 39750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 398e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Callback invoked while the number picker scroll state has changed. 39950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 400e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param view The view whose scroll state is being reported. 401e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param scrollState The current scroll state. One of 402e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_IDLE}, 403e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_TOUCH_SCROLL} or 404e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_IDLE}. 40550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 4064bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void onScrollStateChange(NumberPicker view, int scrollState); 40750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 40850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 40950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 410e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface used to format current value into a string for presentation. 411206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 412206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public interface Formatter { 4134bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 4144bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 415e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Formats a string representation of the current value. 4164bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 4174bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param value The currently selected value. 4184bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @return A formatted string representation. 4194bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 420e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String format(int value); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 422fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 42368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 4244bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Create a new number picker. 4254bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 4264bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param context The application environment. 4274bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 4284bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public NumberPicker(Context context) { 4294bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov this(context, null); 4304bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 4314bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 4324bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 4334bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Create a new number picker. 434206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 435206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param context The application environment. 436206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param attrs A collection of attributes. 43768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public NumberPicker(Context context, AttributeSet attrs) { 439206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov this(context, attrs, R.attr.numberPickerStyle); 440206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 441206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 442206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 443206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Create a new number picker 444206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 445206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param context the application environment. 446206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param attrs a collection of attributes. 447206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param defStyle The default style to apply to this view. 448206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 449206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public NumberPicker(Context context, AttributeSet attrs, int defStyle) { 450206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov super(context, attrs, defStyle); 451206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 452206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // process style attributes 453206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov TypedArray attributesArray = context.obtainStyledAttributes(attrs, 454206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov R.styleable.NumberPicker, defStyle, 0); 455206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSolidColor = attributesArray.getColor(R.styleable.NumberPicker_solidColor, 0); 4564243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mFlingable = attributesArray.getBoolean(R.styleable.NumberPicker_flingable, true); 4579cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider = attributesArray.getDrawable(R.styleable.NumberPicker_selectionDivider); 4589cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int defSelectionDividerHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4599cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT, 4609cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov getResources().getDisplayMetrics()); 4619cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDividerHeight = attributesArray.getDimensionPixelSize( 4629cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight); 463206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov attributesArray.recycle(); 464206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 4659cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mShowInputControlsAnimimationDuration = getResources().getInteger( 4669cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov R.integer.config_longAnimTime); 4679cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 468206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // By default Linearlayout that we extend is not drawn. This is 469206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // its draw() method is not called but dispatchDraw() is called 470206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // directly (see ViewGroup.drawChild()). However, this class uses 471206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // the fading edge effect implemented by View and we need our 472206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // draw() method to be called. Therefore, we declare we will draw. 473206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setWillNotDraw(false); 474206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(false); 475206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 476206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( 477206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Context.LAYOUT_INFLATER_SERVICE); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inflater.inflate(R.layout.number_picker, this, true); 47968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 480206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov OnClickListener onClickListener = new OnClickListener() { 48168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook public void onClick(View v) { 482206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 483206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (v.getId() == R.id.increment) { 484e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov changeCurrent(mValue + 1); 485206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 486e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov changeCurrent(mValue - 1); 48768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 48868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 48968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook }; 49068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 491206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov OnLongClickListener onLongClickListener = new OnLongClickListener() { 492206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onLongClick(View v) { 493206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 494206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (v.getId() == R.id.increment) { 495206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postUpdateValueFromLongPress(UPDATE_STEP_INCREMENT); 496206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 497206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postUpdateValueFromLongPress(UPDATE_STEP_DECREMENT); 498206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 499206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 500206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 501206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 50268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 503206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // increment button 504206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton = (ImageButton) findViewById(R.id.increment); 505206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setOnClickListener(onClickListener); 506206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setOnLongClickListener(onLongClickListener); 507206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 508206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // decrement button 509206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton = (ImageButton) findViewById(R.id.decrement); 510206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setOnClickListener(onClickListener); 511206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setOnLongClickListener(onLongClickListener); 512206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 513206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // input text 514012dd5a461f18a2e5dad38c60282fac1c21ff7feSvetoslav Ganov mInputText = (EditText) findViewById(R.id.numberpicker_input); 515206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setOnFocusChangeListener(new OnFocusChangeListener() { 516206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onFocusChange(View v, boolean hasFocus) { 51768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook if (!hasFocus) { 518206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov validateInputTextView(v); 51968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 52068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 521206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 522206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setFilters(new InputFilter[] { 523206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov new InputTextFilter() 524206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 52568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 526206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 527206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 528206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // initialize constants 529206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTouchSlop = ViewConfiguration.getTapTimeout(); 530206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ViewConfiguration configuration = ViewConfiguration.get(context); 531206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTouchSlop = configuration.getScaledTouchSlop(); 532206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); 533206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity() 534206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov / SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT; 535206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTextSize = (int) mInputText.getTextSize(); 536206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 537206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the selector wheel paint 538206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Paint paint = new Paint(); 539206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setAntiAlias(true); 540206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTextAlign(Align.CENTER); 541206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTextSize(mTextSize); 542206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTypeface(mInputText.getTypeface()); 543206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ColorStateList colors = mInputText.getTextColors(); 544206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int color = colors.getColorForState(ENABLED_STATE_SET, Color.WHITE); 545206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setColor(color); 546206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint = paint; 547206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 548206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the animator for showing the input controls 549206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ValueAnimator fadeScroller = ObjectAnimator.ofInt(this, "selectorPaintAlpha", 255, 0); 550206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ObjectAnimator showIncrementButton = ObjectAnimator.ofFloat(mIncrementButton, 551206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov "alpha", 0, 1); 55201fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov final ObjectAnimator showInputText = ObjectAnimator.ofFloat(mInputText, 55301fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov "alpha", 0, 1); 554206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ObjectAnimator showDecrementButton = ObjectAnimator.ofFloat(mDecrementButton, 555206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov "alpha", 0, 1); 556206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator = new AnimatorSet(); 557206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.playTogether(fadeScroller, showIncrementButton, 55801fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov showInputText, showDecrementButton); 559206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.addListener(new AnimatorListenerAdapter() { 560206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mCanceled = false; 561206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 562206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 563206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onAnimationEnd(Animator animation) { 564206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mCanceled) { 565206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // if canceled => we still want the wheel drawn 566206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(false); 56768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 568206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCanceled = false; 569206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint.setAlpha(255); 570206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 57168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 57268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 573206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 574206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onAnimationCancel(Animator animation) { 575206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mShowInputControlsAnimator.isRunning()) { 576206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCanceled = true; 577206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 578206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 579206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 58068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 581206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the fling and adjust scrollers 582bf80562d22b2bbe7944d80d0524c69d0238010cbSvetoslav Ganov mFlingScroller = new Scroller(getContext(), null, true); 5839cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mAdjustScroller = new Scroller(getContext(), new DecelerateInterpolator(2.5f)); 584fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 585206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 586206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 5879cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 5884fd9dae6a23a22142f73749c291c9fd18459e381Svetoslav Ganov if (mFlingable && !isInEditMode()) { 5899cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // Start with shown selector wheel and hidden controls. When made 5909cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // visible hide the selector and fade-in the controls to suggest 5919cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // fling interaction. 5929cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov setDrawSelectorWheel(true); 5939cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov hideInputControls(); 5949cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 595206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 596206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 597206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 5989cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 5999cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov super.onLayout(changed, left, top, right, bottom); 6009cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // need to do this when we know our size 6019cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov initializeScrollWheel(); 602206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 603206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 604206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 605206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onInterceptTouchEvent(MotionEvent event) { 6064243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (!isEnabled() || !mFlingable) { 60751c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return false; 60851c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 609206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (event.getActionMasked()) { 610206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_DOWN: 611206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mLastMotionEventY = mLastDownEventY = event.getY(); 612206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 613092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov mShowInputControlsAnimator.cancel(); 614206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 615206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = true; 616206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDrawSelectorWheel) { 61750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov boolean scrollersFinished = mFlingScroller.isFinished() 618206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov && mAdjustScroller.isFinished(); 61950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (!scrollersFinished) { 62050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mFlingScroller.forceFinished(true); 62150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mAdjustScroller.forceFinished(true); 6229cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 62350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 62450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mBeginEditOnUpEvent = scrollersFinished; 625206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = true; 626092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 627206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 628206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 62958f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov if (isEventInViewHitRect(event, mInputText) 63058f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov || (!mIncrementButton.isShown() 63158f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && isEventInViewHitRect(event, mIncrementButton)) 63258f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov || (!mDecrementButton.isShown() 63358f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && isEventInViewHitRect(event, mDecrementButton))) { 634206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = false; 635206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(true); 636092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 637206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 638206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 639206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 640206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_MOVE: 641206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float currentMoveY = event.getY(); 642206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 643206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 644206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 6459cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 646206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(true); 647092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 648206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 649206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 650206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 651206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 652206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return false; 653206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 654206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 655206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 656206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onTouchEvent(MotionEvent ev) { 65751c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov if (!isEnabled()) { 65851c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return false; 65951c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 660206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mVelocityTracker == null) { 661206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = VelocityTracker.obtain(); 662206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 663206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.addMovement(ev); 664206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = ev.getActionMasked(); 665206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (action) { 666206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_MOVE: 667206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float currentMoveY = ev.getY(); 66850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (mBeginEditOnUpEvent 66950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov || mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 670206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 671206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 672206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 6739cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 674206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 675206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 676206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaMoveY = (int) (currentMoveY - mLastMotionEventY); 677206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, deltaMoveY); 678206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 679206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mLastMotionEventY = currentMoveY; 680206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 681206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_UP: 682206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mBeginEditOnUpEvent) { 683206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(false); 6849cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 685206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.requestFocus(); 686206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov InputMethodManager imm = (InputMethodManager) getContext().getSystemService( 687206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Context.INPUT_METHOD_SERVICE); 688206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov imm.showSoftInput(mInputText, 0); 68950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mInputText.setSelection(0, mInputText.getText().length()); 690206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 691206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 692206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov VelocityTracker velocityTracker = mVelocityTracker; 693206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); 694206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int initialVelocity = (int) velocityTracker.getYVelocity(); 695206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (Math.abs(initialVelocity) > mMinimumFlingVelocity) { 696206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov fling(initialVelocity); 6979cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); 698206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 699206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerOnUpEvent) { 700206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mFlingScroller.isFinished() && mAdjustScroller.isFinished()) { 701206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(0); 702206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 703206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 704206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(SHOW_INPUT_CONTROLS_DELAY_MILLIS); 705206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 706206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 707206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.recycle(); 708206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = null; 709206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 710206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 711206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 712206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 713206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 714206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 715206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTouchEvent(MotionEvent event) { 716206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = event.getActionMasked(); 717206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ((action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) 71858f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && !isEventInViewHitRect(event, mInputText)) { 719206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 720206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 721206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTouchEvent(event); 722206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 723206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 724206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 725206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchKeyEvent(KeyEvent event) { 726206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int keyCode = event.getKeyCode(); 727206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) { 728206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 729206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 730206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchKeyEvent(event); 731206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 732206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 733206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 734206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTrackballEvent(MotionEvent event) { 735206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = event.getActionMasked(); 736206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 737206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 738206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 739206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTrackballEvent(event); 740206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 742206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 743206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void computeScroll() { 744206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mDrawSelectorWheel) { 745206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 746206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 747206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller scroller = mFlingScroller; 748206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 749206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller = mAdjustScroller; 750206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 751206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 752206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 753206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 754206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller.computeScrollOffset(); 755206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int currentScrollerY = scroller.getCurrY(); 756206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mPreviousScrollerY == 0) { 757206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = scroller.getStartY(); 758206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 759206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, currentScrollerY - mPreviousScrollerY); 760206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = currentScrollerY; 761206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 762206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov onScrollerFinished(scroller); 763206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 764206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 767fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setEnabled(boolean enabled) { 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setEnabled(enabled); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIncrementButton.setEnabled(enabled); 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDecrementButton.setEnabled(enabled); 773206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setEnabled(enabled); 774206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 775206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 776206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 777206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void scrollBy(int x, int y) { 778206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 77934c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (!mWrapSelectorWheel && y > 0 78034c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { 781206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 782206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 783206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 78434c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (!mWrapSelectorWheel && y < 0 78534c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { 786206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 787206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 788206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 789206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += y; 7906c742f1e95dfe1f808bf02fadd5fbf9660b95050Svetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset >= mSelectorElementHeight) { 791206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset -= mSelectorElementHeight; 792206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov decrementSelectorIndices(selectorIndices); 793206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); 794e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { 795206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 796206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 797206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 7986c742f1e95dfe1f808bf02fadd5fbf9660b95050Svetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset <= -mSelectorElementHeight) { 799206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += mSelectorElementHeight; 800206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov incrementScrollSelectorIndices(selectorIndices); 801206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); 802e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { 803206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 804206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 805206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 807fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 8084bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov @Override 8094bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public int getSolidColor() { 8104bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov return mSolidColor; 8114bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 8124bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 81368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 8144bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the listener to be notified on change of the current value. 815206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 816e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param onValueChangedListener The listener. 81768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 818cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov public void setOnValueChangedListener(OnValueChangeListener onValueChangedListener) { 819cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mOnValueChangeListener = onValueChangedListener; 82050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 82150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 82250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 8234bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set listener to be notified for scroll state changes. 82450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 825e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param onScrollListener The listener. 82650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 82750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public void setOnScrollListener(OnScrollListener onScrollListener) { 82850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mOnScrollListener = onScrollListener; 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 830fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 83168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 8324bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set the formatter to be used for formatting the current value. 8334bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 834e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Note: If you have provided alternative values for the values this 835e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * formatter is never invoked. 8364bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 837206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 838e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param formatter The formatter object. If formatter is <code>null</code>, 839e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link String#valueOf(int)} will be used. 8404bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 841e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setDisplayedValues(String[]) 84268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFormatter(Formatter formatter) { 844e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (formatter == mFormatter) { 845e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 846e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFormatter = formatter; 848e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 8499cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov updateInputTextView(); 850206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 851206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 852206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 853e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Set the current value for the number picker. 8544bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 855e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMinValue()} and 856e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the 857e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMinValue()} value. 858e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 859e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 860e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMinValue()} and 861e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the 862e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMaxValue()} value. 863e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 864e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 865e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMaxValue()} and 866e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the 867e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMaxValue()} value. 868e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 869e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 870e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMaxValue()} and 871e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the 872e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMinValue()} value. 8734bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 874206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 875e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param value The current value. 8764bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @see #setWrapSelectorWheel(boolean) 877e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setMinValue(int) 878e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setMaxValue(int) 879206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 880e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setValue(int value) { 881e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mValue == value) { 882a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov return; 883a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 884e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (value < mMinValue) { 885e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov value = mWrapSelectorWheel ? mMaxValue : mMinValue; 886206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 887e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (value > mMaxValue) { 888e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov value = mWrapSelectorWheel ? mMinValue : mMaxValue; 8898bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powell } 890e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = value; 891e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 892e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 894fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 89568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 896e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Gets whether the selector wheel wraps when reaching the min/max value. 89768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 898e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return True if the selector wheel wraps. 8994bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 900e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #getMinValue() 901e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #getMaxValue() 90268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 903e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public boolean getWrapSelectorWheel() { 904e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mWrapSelectorWheel; 905206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 906206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 907206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 908e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets whether the selector wheel shown during flinging/scrolling should 909e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * wrap around the {@link NumberPicker#getMinValue()} and 910e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getMaxValue()} values. 911e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 912e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * By default if the range (max - min) is more than five (the number of 913e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * items shown on the selector wheel) the selector wheel wrapping is 914e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * enabled. 915e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 916206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 917206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param wrapSelector Whether to wrap. 918206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 9194bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setWrapSelectorWheel(boolean wrapSelector) { 920e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (wrapSelector && (mMaxValue - mMinValue) < mSelectorIndices.length) { 921206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov throw new IllegalStateException("Range less than selector items count."); 922206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 923e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (wrapSelector != mWrapSelectorWheel) { 924206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // force the selector indices array to be reinitialized 925206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] = Integer.MAX_VALUE; 926e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mWrapSelectorWheel = wrapSelector; 927156f20919b3d5f298f8851215adbf65f8b4dc61bSvetoslav Ganov // force redraw since we might look different 928156f20919b3d5f298f8851215adbf65f8b4dc61bSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 929206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9334bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the speed at which the numbers be incremented and decremented when 9344bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * the up and down buttons are long pressed respectively. 935e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 936e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * The default value is 300 ms. 937e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 93868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 9394bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param intervalMillis The speed (in milliseconds) at which the numbers 940e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * will be incremented and decremented. 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9424bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setOnLongPressUpdateInterval(long intervalMillis) { 9434bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mLongPressUpdateInterval = intervalMillis; 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 945fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 946206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 947e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the value of the picker. 948e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 949e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The value. 950e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 951e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getValue() { 952e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mValue; 953e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 954e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 955e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 956e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the min value of the picker. 957e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 958e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The min value 959e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 960e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getMinValue() { 961e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue; 962e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 963e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 964e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 965e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the min value of the picker. 966206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 967e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param minValue The min value. 968206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 969e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setMinValue(int minValue) { 970e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMinValue == minValue) { 971e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 972e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 973e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (minValue < 0) { 974e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov throw new IllegalArgumentException("minValue must be >= 0"); 975e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 976e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinValue = minValue; 977e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMinValue > mValue) { 978e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = mMinValue; 979e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 980e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; 981e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 982e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 983e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 984206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 985206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 9864bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 987e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the max value of the picker. 9884bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 989e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The max value. 9904bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 991e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getMaxValue() { 992e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMaxValue; 9934bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 9944bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 9954bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 996e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the max value of the picker. 9974bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 998e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param maxValue The max value. 9994bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 1000e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setMaxValue(int maxValue) { 1001e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMaxValue == maxValue) { 1002e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1003e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1004e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (maxValue < 0) { 1005e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov throw new IllegalArgumentException("maxValue must be >= 0"); 1006e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1007e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMaxValue = maxValue; 1008e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMaxValue < mValue) { 1009e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = mMaxValue; 1010e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1011e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; 1012e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 1013e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 1014e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1015e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1016e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1017e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1018e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Gets the values to be displayed instead of string values. 1019e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1020e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The displayed values. 1021e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1022e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String[] getDisplayedValues() { 1023e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mDisplayedValues; 1024e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1025e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1026e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1027e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the values to be displayed. 1028e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1029e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param displayedValues The displayed values. 1030e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1031e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setDisplayedValues(String[] displayedValues) { 1032e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mDisplayedValues == displayedValues) { 1033e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1034e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1035e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mDisplayedValues = displayedValues; 1036e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mDisplayedValues != null) { 1037e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov // Allow text entry rather than strictly numeric entry. 1038e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT 1039e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); 1040e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } else { 1041e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 1042e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1043e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1044e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 1045206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1046206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1047206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1048206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getTopFadingEdgeStrength() { 1049206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 1050206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1051206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1052206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1053206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getBottomFadingEdgeStrength() { 1054206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 1055206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1056206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1057206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 10589cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov protected void onAttachedToWindow() { 10599cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov super.onAttachedToWindow(); 10609cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // make sure we show the controls only the very 10619cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // first time the user sees this widget 10624fd9dae6a23a22142f73749c291c9fd18459e381Svetoslav Ganov if (mFlingable && !isInEditMode()) { 10639cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // animate a bit slower the very first time 10649cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration * 2); 10659cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 10669cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 10679cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 10689cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov @Override 1069206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDetachedFromWindow() { 1070206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 1071206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1072206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1073206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1074206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void dispatchDraw(Canvas canvas) { 1075206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // There is a good reason for doing this. See comments in draw(). 1076206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1077206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1078206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1079206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void draw(Canvas canvas) { 1080206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Dispatch draw to our children only if we are not currently running 1081206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // the animation for simultaneously fading out the scroll wheel and 1082206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // showing in the buttons. This class takes advantage of the View 1083206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // implementation of fading edges effect to draw the selector wheel. 1084206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // However, in View.draw(), the fading is applied after all the children 1085206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // have been drawn and we do not want this fading to be applied to the 1086206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // buttons which are currently showing in. Therefore, we draw our 10879cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // children after we have completed drawing ourselves. 1088c75ec3324e9e3e6500148cc2978caab90ea962e4Chet Haase super.draw(canvas); 1089206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1090206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Draw our children if we are not showing the selector wheel of fading 1091206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // it out 1092206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mShowInputControlsAnimator.isRunning() || !mDrawSelectorWheel) { 1093206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov long drawTime = getDrawingTime(); 1094206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0, count = getChildCount(); i < count; i++) { 1095206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov View child = getChildAt(i); 1096206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!child.isShown()) { 1097206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov continue; 1098206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1099206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov drawChild(canvas, getChildAt(i), drawTime); 1100206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1101206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1102206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1103206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1104206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1105206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDraw(Canvas canvas) { 1106206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // we only draw the selector wheel 1107206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mDrawSelectorWheel) { 1108206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1109206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1110206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float x = (mRight - mLeft) / 2; 1111206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float y = mCurrentScrollOffset; 1112206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 11139cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the selector wheel 1114206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 1115206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length; i++) { 1116206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = selectorIndices[i]; 1117206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex); 1118206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov canvas.drawText(scrollSelectorValue, x, y, mSelectorPaint); 1119206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov y += mSelectorElementHeight; 1120206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 11219cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 11229cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the selection dividers (only if scrolling and drawable specified) 11239cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mSelectionDivider != null) { 11249cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setAlpha(mSelectorPaint.getAlpha()); 11259cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the top divider 11269cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int topOfTopDivider = 11279cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov (getHeight() - mSelectorElementHeight - mSelectionDividerHeight) / 2; 11289cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int bottomOfTopDivider = topOfTopDivider + mSelectionDividerHeight; 11299cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setBounds(0, topOfTopDivider, mRight, bottomOfTopDivider); 11309cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.draw(canvas); 11319cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 11329cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the bottom divider 11339cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int topOfBottomDivider = topOfTopDivider + mSelectorElementHeight; 11349cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int bottomOfBottomDivider = bottomOfTopDivider + mSelectorElementHeight; 11359cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setBounds(0, topOfBottomDivider, mRight, bottomOfBottomDivider); 11369cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.draw(canvas); 11379cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 114068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1141a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov * Resets the selector indices and clear the cached 1142a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov * string representation of these indices. 1143a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov */ 1144e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private void resetSelectorWheelIndices() { 1145a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov mSelectorIndexToStringCache.clear(); 1146a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov int[] selectorIdices = getSelectorIndices(); 1147a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov for (int i = 0; i < selectorIdices.length; i++) { 1148a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov selectorIdices[i] = Integer.MIN_VALUE; 1149a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1150a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1151a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov 1152a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov /** 1153206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets the current value of this NumberPicker, and sets mPrevious to the 1154206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * previous value. If current is greater than mEnd less than mStart, the 1155206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * value of mCurrent is wrapped around. Subclasses can override this to 1156206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * change the wrapping behavior 115768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 115868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * @param current the new value of the NumberPicker 115968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1160206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void changeCurrent(int current) { 1161e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mValue == current) { 1162206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1163206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wrap around the values if we go past the start or end 1165e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1166206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov current = getWrappedSelectorIndex(current); 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1168e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int previous = mValue; 1169e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setValue(current); 1170206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov notifyChange(previous, current); 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1172fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 117368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1174206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets the <code>alpha</code> of the {@link Paint} for drawing the selector 1175206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * wheel. 117668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1177206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @SuppressWarnings("unused") 1178206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Called by ShowInputControlsAnimator via reflection 1179206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setSelectorPaintAlpha(int alpha) { 1180206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint.setAlpha(alpha); 1181206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDrawSelectorWheel) { 1182206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 118668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 118758f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov * @return If the <code>event</code> is in the <code>view</code>. 118868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 118958f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov private boolean isEventInViewHitRect(MotionEvent event, View view) { 119058f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov view.getHitRect(mTempRect); 1191206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mTempRect.contains((int) event.getX(), (int) event.getY()); 1192206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1193206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1194206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1195206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets if to <code>drawSelectionWheel</code>. 1196206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1197206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setDrawSelectorWheel(boolean drawSelectorWheel) { 1198206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDrawSelectorWheel = drawSelectorWheel; 1199206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // do not fade if the selector wheel not shown 1200206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setVerticalFadingEdgeEnabled(drawSelectorWheel); 1201206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1202206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 12039cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void initializeScrollWheel() { 12049cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mInitialScrollOffset != Integer.MIN_VALUE) { 12059cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov return; 12069cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 12079cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12089cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 12099cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int totalTextHeight = selectorIndices.length * mTextSize; 121001fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov float totalTextGapHeight = (mBottom - mTop) - totalTextHeight; 121101fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov float textGapCount = selectorIndices.length - 1; 121201fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov int selectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f); 121301fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov // Compensate if text size is odd since every time we get its middle a pixel is lost. 121401fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov mInitialScrollOffset = mCurrentScrollOffset = mTextSize - (3 * (mTextSize % 2)); 12159cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectorElementHeight = mTextSize + selectorTextGapHeight; 12169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov updateInputTextView(); 12179cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12189cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 1219206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1220206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Callback invoked upon completion of a given <code>scroller</code>. 1221206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1222206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void onScrollerFinished(Scroller scroller) { 1223206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller == mFlingScroller) { 1224206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(0); 12259cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1227206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 12289cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1231fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1232206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 12339cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * Handles transition to a given <code>scrollState</code> 123450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 12359cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void onScrollStateChange(int scrollState) { 12369cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mScrollState == scrollState) { 12379cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov return; 12389cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12399cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mScrollState = scrollState; 12409cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mOnScrollListener != null) { 12414bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mOnScrollListener.onScrollStateChange(this, scrollState); 124250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 124350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 124450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 124550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 1246206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flings the selector with the given <code>velocityY</code>. 1247206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1248206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void fling(int velocityY) { 1249206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 1250206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller flingScroller = mFlingScroller; 1251206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1252e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1253206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (velocityY > 0) { 1254206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1255206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1256206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1257206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1258206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1259206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (velocityY > 0) { 1260e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int maxY = mTextSize * (mValue - mMinValue); 1261206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, maxY); 1262206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1263e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int startY = mTextSize * (mMaxValue - mValue); 1264206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int maxY = startY; 1265206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, startY, 0, velocityY, 0, 0, 0, maxY); 12662bf761c20253222a763bce9a63d14c48ab08a556Suchi Amalapurapu } 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1268206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1269206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1272206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1273206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Hides the input controls which is the up/down arrows and the text field. 1274206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1275206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void hideInputControls() { 1276206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.cancel(); 1277206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(INVISIBLE); 1278206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(INVISIBLE); 1279206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setVisibility(INVISIBLE); 1280206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1281c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1282206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1283206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Show the input controls by making them visible and animating the alpha 1284206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * property up/down arrows. 12859cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * 12869cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * @param animationDuration The duration of the animation. 1287206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 12889cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void showInputControls(long animationDuration) { 1289206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 1290206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setVisibility(VISIBLE); 12919cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mShowInputControlsAnimator.setDuration(animationDuration); 1292206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.start(); 1293206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1294c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1295206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1296206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the visibility state of the increment and decrement buttons. 1297206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1298206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void updateIncrementAndDecrementButtonsVisibilityState() { 1299e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel || mValue < mMaxValue) { 1300206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(VISIBLE); 1301206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1302206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(INVISIBLE); 1303206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1304e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel || mValue > mMinValue) { 1305206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(VISIBLE); 1306206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1307206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(INVISIBLE); 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1312206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selector indices array with proper values with the current as 1313206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * the middle one. 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1315206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int[] getSelectorIndices() { 1316e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int current = getValue(); 1317206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] != current) { 1318206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < mSelectorIndices.length; i++) { 1319206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX); 1320e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1321206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndex = getWrappedSelectorIndex(selectorIndex); 1322206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1323206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorIndices[i] = selectorIndex; 1324206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(mSelectorIndices[i]); 1325206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1326206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1327206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mSelectorIndices; 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 133068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1331206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The wrapped index <code>selectorIndex</code> value. 133268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1333206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getWrappedSelectorIndex(int selectorIndex) { 1334e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndex > mMaxValue) { 1335e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1; 1336e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } else if (selectorIndex < mMinValue) { 1337e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1; 1338206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1339206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return selectorIndex; 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1341fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1342206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1343206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Increments the <code>selectorIndices</code> whose string representations 1344206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1345206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1346206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void incrementScrollSelectorIndices(int[] selectorIndices) { 1347206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length - 1; i++) { 1348206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i + 1]; 1349206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1350206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[selectorIndices.length - 2] + 1; 1351e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel && nextScrollSelectorIndex > mMaxValue) { 1352e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov nextScrollSelectorIndex = mMinValue; 1353206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1354206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[selectorIndices.length - 1] = nextScrollSelectorIndex; 1355206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1356206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1357fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1358206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1359206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Decrements the <code>selectorIndices</code> whose string representations 1360206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1361206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1362206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void decrementSelectorIndices(int[] selectorIndices) { 1363206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = selectorIndices.length - 1; i > 0; i--) { 1364206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i - 1]; 1365206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1366206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[1] - 1; 1367e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel && nextScrollSelectorIndex < mMinValue) { 1368e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov nextScrollSelectorIndex = mMaxValue; 1369206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1370206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[0] = nextScrollSelectorIndex; 1371206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1372206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1373fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1374206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1375206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensures we have a cached string representation of the given <code> 1376206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * selectorIndex</code> 1377206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * to avoid multiple instantiations of the same string. 1378206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1379206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void ensureCachedScrollSelectorValue(int selectorIndex) { 1380206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov SparseArray<String> cache = mSelectorIndexToStringCache; 1381206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = cache.get(selectorIndex); 1382206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scrollSelectorValue != null) { 1383206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1384206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1385e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndex < mMinValue || selectorIndex > mMaxValue) { 1386206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = ""; 1387206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1388206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues != null) { 1389e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int displayedValueIndex = selectorIndex - mMinValue; 139050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov scrollSelectorValue = mDisplayedValues[displayedValueIndex]; 1391206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1392206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = formatNumber(selectorIndex); 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1395206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov cache.put(selectorIndex, scrollSelectorValue); 13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1397fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1398206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private String formatNumber(int value) { 1399e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return (mFormatter != null) ? mFormatter.format(value) : String.valueOf(value); 1400206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1402206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void validateInputTextView(View v) { 1403206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(((TextView) v).getText()); 1404206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(str)) { 1405206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Restore to the old value as we don't allow empty values 1406206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 1407206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1408206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Check the new value and ensure it's in range 1409206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int current = getSelectedPos(str.toString()); 1410206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(current); 14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1412206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1413fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1414206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1415206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the view of this NumberPicker. If displayValues were specified in 14169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * the string corresponding to the index specified by the current value will 14179cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * be returned. Otherwise, the formatter specified in {@link #setFormatter} 14189cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * will be used to format the number. 1419206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1420206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void updateInputTextView() { 1421206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1422206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * If we don't have displayed values then use the current number else 1423206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * find the correct value in the displayed values for the current 1424206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * number. 1425206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1426206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 1427e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setText(formatNumber(mValue)); 1428206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1429e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setText(mDisplayedValues[mValue - mMinValue]); 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1431206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mInputText.getText().length()); 1432206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1433fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1434206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1435206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Notifies the listener, if registered, of a change of the value of this 1436206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * NumberPicker. 1437206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1438206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void notifyChange(int previous, int current) { 1439cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov if (mOnValueChangeListener != null) { 1440cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mOnValueChangeListener.onValueChange(this, previous, mValue); 1441206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1442206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1444206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1445206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts a command for updating the current value every <code>updateMillis 1446206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * </code>. 1447206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1448206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postUpdateValueFromLongPress(int updateMillis) { 1449206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 1450206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 1451206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mUpdateFromLongPressCommand == null) { 1452206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateFromLongPressCommand = new UpdateValueFromLongPressCommand(); 1453206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1454206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateFromLongPressCommand.setUpdateStep(updateMillis); 1455206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mUpdateFromLongPressCommand); 1456206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1458206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1459206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Removes all pending callback from the message queue. 1460206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1461206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void removeAllCallbacks() { 1462206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mUpdateFromLongPressCommand != null) { 1463206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mUpdateFromLongPressCommand); 1464206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1465206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerCommand != null) { 1466206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mAdjustScrollerCommand); 1467206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1468206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand != null) { 1469206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1473206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1474206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selected index given its displayed <code>value</code>. 1475206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1476206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getSelectedPos(String value) { 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisplayedValues == null) { 1478aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy try { 1479206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 1480aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } catch (NumberFormatException e) { 1481206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 1482aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mDisplayedValues.length; i++) { 1485206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Don't force the user to type in jan when ja will do 1486206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov value = value.toLowerCase(); 1487206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues[i].toLowerCase().startsWith(value)) { 1488e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue + i; 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1491fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1492206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1493206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The user might have typed in a number into the month field i.e. 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10 instead of OCT so support that too. 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1497206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 1499fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1500206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1503e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue; 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1507206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link SetSelectionCommand} from the given <code>selectionStart 1508206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * </code> to 1509206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * <code>selectionEnd</code>. 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1511206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postSetSelectionCommand(int selectionStart, int selectionEnd) { 1512206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand == null) { 1513206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand = new SetSelectionCommand(); 1514206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1515206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 1516206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1517206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionStart = selectionStart; 1518206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionEnd = selectionEnd; 1519206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mSetSelectionCommand); 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 152168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 152268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1523206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link AdjustScrollerCommand} within the given <code> 1524206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * delayMillis</code> 1525206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * . 152668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1527206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postAdjustScrollerCommand(int delayMillis) { 1528206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerCommand == null) { 1529206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerCommand = new AdjustScrollerCommand(); 1530206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1531206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mAdjustScrollerCommand); 1532206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1533206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postDelayed(mAdjustScrollerCommand, delayMillis); 153468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 153568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 153668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1537206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Filter for accepting only valid indices or prefixes of the string 1538206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * representation of valid indices. 153968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1540206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class InputTextFilter extends NumberKeyListener { 1541206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1542206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // XXX This doesn't allow for range limits when controlled by a 1543206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // soft input method! 1544206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public int getInputType() { 1545206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return InputType.TYPE_CLASS_TEXT; 1546206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1547206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1548206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1549206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected char[] getAcceptedChars() { 1550206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return DIGIT_CHARACTERS; 1551206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1552206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1553206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1554206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public CharSequence filter(CharSequence source, int start, int end, Spanned dest, 1555206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int dstart, int dend) { 1556206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 1557206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = super.filter(source, start, end, dest, dstart, dend); 1558206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (filtered == null) { 1559206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov filtered = source.subSequence(start, end); 1560206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1561206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1562206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 1563206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 1564206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1565206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ("".equals(result)) { 1566206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return result; 1567206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1568206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int val = getSelectedPos(result); 1569206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1570206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1571206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensure the user can't type in a value greater than the max 1572206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * allowed. We have to allow less than min as the user might 1573206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * want to delete some numbers and then type a new number. 1574206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1575e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (val > mMaxValue) { 1576206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1577206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1578206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return filtered; 1579206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1580206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1581206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = String.valueOf(source.subSequence(start, end)); 1582206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(filtered)) { 1583206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1584206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1585206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 1586206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 1587206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(result).toLowerCase(); 1588206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (String val : mDisplayedValues) { 1589206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String valLowerCase = val.toLowerCase(); 1590206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (valLowerCase.startsWith(str)) { 1591206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postSetSelectionCommand(result.length(), val.length()); 1592206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return val.subSequence(dstart, val.length()); 1593206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1594206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1595206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1596206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1597206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1598206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1599206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1600206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1601206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for setting the input text selection. 1602206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1603206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class SetSelectionCommand implements Runnable { 1604206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionStart; 1605206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1606206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionEnd; 1607206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1608206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1609206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mSelectionStart, mSelectionEnd); 1610206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1611206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1612206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1613206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1614206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for adjusting the scroller to show in its center the closest of 1615206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * the displayed items. 1616206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1617206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class AdjustScrollerCommand implements Runnable { 1618206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1619206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 162034c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (mInitialScrollOffset == mCurrentScrollOffset) { 162134c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov updateInputTextView(); 16229cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 162334c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov return; 162434c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov } 162534c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov // adjust to the closest value 1626206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaY = mInitialScrollOffset - mCurrentScrollOffset; 162734c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (Math.abs(deltaY) > mSelectorElementHeight / 2) { 162834c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov deltaY += (deltaY > 0) ? -mSelectorElementHeight : mSelectorElementHeight; 162934c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov } 16309cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mAdjustScroller.startScroll(0, 0, 0, deltaY, SELECTOR_ADJUSTMENT_DURATION_MILLIS); 1631206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 1632206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1633206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1634206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1635206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1636206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for updating the current value from a long press. 1637206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1638206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class UpdateValueFromLongPressCommand implements Runnable { 1639206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mUpdateStep = 0; 1640206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1641206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setUpdateStep(int updateStep) { 1642206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateStep = updateStep; 1643206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1644206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1645206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1646e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov changeCurrent(mValue + mUpdateStep); 16474bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov postDelayed(this, mLongPressUpdateInterval); 1648206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 164968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 16507762d93621f508f4410fd37b5bbdfec0071b0420Paul Westbrook} 1651