NumberPicker.java revision 5203194fdff0c0aaefc405d65871ef0e06e7c682
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); 552206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ObjectAnimator showDecrementButton = ObjectAnimator.ofFloat(mDecrementButton, 553206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov "alpha", 0, 1); 554206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator = new AnimatorSet(); 555206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.playTogether(fadeScroller, showIncrementButton, 5565203194fdff0c0aaefc405d65871ef0e06e7c682Svetoslav Ganov showDecrementButton); 557206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.addListener(new AnimatorListenerAdapter() { 558206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mCanceled = false; 559206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 560206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 561206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onAnimationEnd(Animator animation) { 562206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mCanceled) { 563206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // if canceled => we still want the wheel drawn 564206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(false); 56568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 566206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCanceled = false; 567206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint.setAlpha(255); 568206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 56968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 57068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 571206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 572206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onAnimationCancel(Animator animation) { 573206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mShowInputControlsAnimator.isRunning()) { 574206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCanceled = true; 575206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 576206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 577206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 57868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 579206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the fling and adjust scrollers 580bf80562d22b2bbe7944d80d0524c69d0238010cbSvetoslav Ganov mFlingScroller = new Scroller(getContext(), null, true); 5819cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mAdjustScroller = new Scroller(getContext(), new DecelerateInterpolator(2.5f)); 582fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 583206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 584206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 5859cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 5864fd9dae6a23a22142f73749c291c9fd18459e381Svetoslav Ganov if (mFlingable && !isInEditMode()) { 5879cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // Start with shown selector wheel and hidden controls. When made 5889cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // visible hide the selector and fade-in the controls to suggest 5899cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // fling interaction. 5909cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov setDrawSelectorWheel(true); 5919cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov hideInputControls(); 5929cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 593206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 594206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 595206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 5969cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 5979cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov super.onLayout(changed, left, top, right, bottom); 5989cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // need to do this when we know our size 5999cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov initializeScrollWheel(); 600206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 601206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 602206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 603206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onInterceptTouchEvent(MotionEvent event) { 6044243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (!isEnabled() || !mFlingable) { 60551c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return false; 60651c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 607206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (event.getActionMasked()) { 608206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_DOWN: 609206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mLastMotionEventY = mLastDownEventY = event.getY(); 610206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 611092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov mShowInputControlsAnimator.cancel(); 612206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 613206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = true; 614206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDrawSelectorWheel) { 61550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov boolean scrollersFinished = mFlingScroller.isFinished() 616206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov && mAdjustScroller.isFinished(); 61750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (!scrollersFinished) { 61850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mFlingScroller.forceFinished(true); 61950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mAdjustScroller.forceFinished(true); 6209cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 62150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 62250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mBeginEditOnUpEvent = scrollersFinished; 623206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = true; 624092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 625206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 626206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 62758f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov if (isEventInViewHitRect(event, mInputText) 62858f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov || (!mIncrementButton.isShown() 62958f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && isEventInViewHitRect(event, mIncrementButton)) 63058f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov || (!mDecrementButton.isShown() 63158f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && isEventInViewHitRect(event, mDecrementButton))) { 632206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = false; 633206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(true); 634092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 635206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 636206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 637206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 638206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_MOVE: 639206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float currentMoveY = event.getY(); 640206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 641206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 642206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 6439cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 644206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(true); 645092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 646206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 647206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 648206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 649206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 650206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return false; 651206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 652206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 653206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 654206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onTouchEvent(MotionEvent ev) { 65551c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov if (!isEnabled()) { 65651c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return false; 65751c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 658206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mVelocityTracker == null) { 659206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = VelocityTracker.obtain(); 660206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 661206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.addMovement(ev); 662206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = ev.getActionMasked(); 663206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (action) { 664206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_MOVE: 665206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float currentMoveY = ev.getY(); 66650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (mBeginEditOnUpEvent 66750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov || mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 668206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 669206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 670206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 6719cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 672206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 673206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 674206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaMoveY = (int) (currentMoveY - mLastMotionEventY); 675206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, deltaMoveY); 676206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 677206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mLastMotionEventY = currentMoveY; 678206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 679206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_UP: 680206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mBeginEditOnUpEvent) { 681206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(false); 6829cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 683206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.requestFocus(); 684206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov InputMethodManager imm = (InputMethodManager) getContext().getSystemService( 685206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Context.INPUT_METHOD_SERVICE); 686206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov imm.showSoftInput(mInputText, 0); 68750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mInputText.setSelection(0, mInputText.getText().length()); 688206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 689206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 690206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov VelocityTracker velocityTracker = mVelocityTracker; 691206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); 692206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int initialVelocity = (int) velocityTracker.getYVelocity(); 693206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (Math.abs(initialVelocity) > mMinimumFlingVelocity) { 694206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov fling(initialVelocity); 6959cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); 696206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 697206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerOnUpEvent) { 698206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mFlingScroller.isFinished() && mAdjustScroller.isFinished()) { 699206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(0); 700206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 701206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 702206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(SHOW_INPUT_CONTROLS_DELAY_MILLIS); 703206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 704206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 705206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.recycle(); 706206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = null; 707206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 708206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 709206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 710206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 711206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 712206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 713206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTouchEvent(MotionEvent event) { 714206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = event.getActionMasked(); 715206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ((action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) 71658f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && !isEventInViewHitRect(event, mInputText)) { 717206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 718206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 719206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTouchEvent(event); 720206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 721206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 722206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 723206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchKeyEvent(KeyEvent event) { 724206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int keyCode = event.getKeyCode(); 725206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) { 726206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 727206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 728206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchKeyEvent(event); 729206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 730206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 731206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 732206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTrackballEvent(MotionEvent event) { 733206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = event.getActionMasked(); 734206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 735206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 736206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 737206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTrackballEvent(event); 738206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 740206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 741206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void computeScroll() { 742206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mDrawSelectorWheel) { 743206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 744206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 745206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller scroller = mFlingScroller; 746206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 747206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller = mAdjustScroller; 748206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 749206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 750206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 751206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 752206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller.computeScrollOffset(); 753206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int currentScrollerY = scroller.getCurrY(); 754206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mPreviousScrollerY == 0) { 755206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = scroller.getStartY(); 756206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 757206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, currentScrollerY - mPreviousScrollerY); 758206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = currentScrollerY; 759206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 760206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov onScrollerFinished(scroller); 761206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 762206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 765fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setEnabled(boolean enabled) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setEnabled(enabled); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIncrementButton.setEnabled(enabled); 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDecrementButton.setEnabled(enabled); 771206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setEnabled(enabled); 772206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 773206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 774206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 775206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void scrollBy(int x, int y) { 776206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 77734c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (!mWrapSelectorWheel && y > 0 77834c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { 779206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 780206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 781206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 78234c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (!mWrapSelectorWheel && y < 0 78334c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { 784206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 785206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 786206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 787206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += y; 7886c742f1e95dfe1f808bf02fadd5fbf9660b95050Svetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset >= mSelectorElementHeight) { 789206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset -= mSelectorElementHeight; 790206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov decrementSelectorIndices(selectorIndices); 791206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); 792e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { 793206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 794206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 795206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 7966c742f1e95dfe1f808bf02fadd5fbf9660b95050Svetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset <= -mSelectorElementHeight) { 797206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += mSelectorElementHeight; 798206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov incrementScrollSelectorIndices(selectorIndices); 799206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); 800e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { 801206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 802206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 803206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 805fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 8064bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov @Override 8074bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public int getSolidColor() { 8084bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov return mSolidColor; 8094bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 8104bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 81168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 8124bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the listener to be notified on change of the current value. 813206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 814e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param onValueChangedListener The listener. 81568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 816cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov public void setOnValueChangedListener(OnValueChangeListener onValueChangedListener) { 817cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mOnValueChangeListener = onValueChangedListener; 81850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 81950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 82050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 8214bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set listener to be notified for scroll state changes. 82250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 823e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param onScrollListener The listener. 82450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 82550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public void setOnScrollListener(OnScrollListener onScrollListener) { 82650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mOnScrollListener = onScrollListener; 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 828fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 82968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 8304bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set the formatter to be used for formatting the current value. 8314bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 832e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Note: If you have provided alternative values for the values this 833e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * formatter is never invoked. 8344bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 835206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 836e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param formatter The formatter object. If formatter is <code>null</code>, 837e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link String#valueOf(int)} will be used. 8384bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 839e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setDisplayedValues(String[]) 84068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFormatter(Formatter formatter) { 842e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (formatter == mFormatter) { 843e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 844e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFormatter = formatter; 846e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 8479cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov updateInputTextView(); 848206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 849206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 850206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 851e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Set the current value for the number picker. 8524bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 853e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMinValue()} and 854e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the 855e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMinValue()} value. 856e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 857e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 858e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMinValue()} and 859e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the 860e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMaxValue()} value. 861e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 862e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 863e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMaxValue()} and 864e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the 865e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMaxValue()} value. 866e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 867e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 868e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMaxValue()} and 869e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the 870e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMinValue()} value. 8714bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 872206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 873e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param value The current value. 8744bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @see #setWrapSelectorWheel(boolean) 875e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setMinValue(int) 876e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setMaxValue(int) 877206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 878e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setValue(int value) { 879e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mValue == value) { 880a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov return; 881a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 882e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (value < mMinValue) { 883e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov value = mWrapSelectorWheel ? mMaxValue : mMinValue; 884206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 885e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (value > mMaxValue) { 886e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov value = mWrapSelectorWheel ? mMinValue : mMaxValue; 8878bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powell } 888e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = value; 889e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 890e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 892fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 89368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 894e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Gets whether the selector wheel wraps when reaching the min/max value. 89568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 896e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return True if the selector wheel wraps. 8974bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 898e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #getMinValue() 899e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #getMaxValue() 90068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 901e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public boolean getWrapSelectorWheel() { 902e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mWrapSelectorWheel; 903206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 904206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 905206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 906e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets whether the selector wheel shown during flinging/scrolling should 907e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * wrap around the {@link NumberPicker#getMinValue()} and 908e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getMaxValue()} values. 909e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 910e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * By default if the range (max - min) is more than five (the number of 911e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * items shown on the selector wheel) the selector wheel wrapping is 912e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * enabled. 913e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 914206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 915206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param wrapSelector Whether to wrap. 916206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 9174bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setWrapSelectorWheel(boolean wrapSelector) { 918e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (wrapSelector && (mMaxValue - mMinValue) < mSelectorIndices.length) { 919206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov throw new IllegalStateException("Range less than selector items count."); 920206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 921e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (wrapSelector != mWrapSelectorWheel) { 922206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // force the selector indices array to be reinitialized 923206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] = Integer.MAX_VALUE; 924e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mWrapSelectorWheel = wrapSelector; 925156f20919b3d5f298f8851215adbf65f8b4dc61bSvetoslav Ganov // force redraw since we might look different 926156f20919b3d5f298f8851215adbf65f8b4dc61bSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 927206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9314bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the speed at which the numbers be incremented and decremented when 9324bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * the up and down buttons are long pressed respectively. 933e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 934e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * The default value is 300 ms. 935e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 93668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 9374bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param intervalMillis The speed (in milliseconds) at which the numbers 938e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * will be incremented and decremented. 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9404bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setOnLongPressUpdateInterval(long intervalMillis) { 9414bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mLongPressUpdateInterval = intervalMillis; 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 943fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 944206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 945e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the value of the picker. 946e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 947e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The value. 948e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 949e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getValue() { 950e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mValue; 951e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 952e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 953e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 954e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the min value of the picker. 955e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 956e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The min value 957e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 958e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getMinValue() { 959e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue; 960e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 961e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 962e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 963e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the min value of the picker. 964206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 965e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param minValue The min value. 966206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 967e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setMinValue(int minValue) { 968e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMinValue == minValue) { 969e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 970e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 971e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (minValue < 0) { 972e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov throw new IllegalArgumentException("minValue must be >= 0"); 973e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 974e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinValue = minValue; 975e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMinValue > mValue) { 976e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = mMinValue; 977e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 978e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; 979e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 980e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 981e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 982206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 983206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 9844bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 985e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the max value of the picker. 9864bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 987e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The max value. 9884bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 989e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getMaxValue() { 990e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMaxValue; 9914bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 9924bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 9934bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 994e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the max value of the picker. 9954bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 996e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param maxValue The max value. 9974bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 998e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setMaxValue(int maxValue) { 999e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMaxValue == maxValue) { 1000e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1001e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1002e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (maxValue < 0) { 1003e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov throw new IllegalArgumentException("maxValue must be >= 0"); 1004e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1005e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMaxValue = maxValue; 1006e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMaxValue < mValue) { 1007e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = mMaxValue; 1008e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1009e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; 1010e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 1011e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 1012e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1013e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1014e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1015e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1016e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Gets the values to be displayed instead of string values. 1017e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1018e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The displayed values. 1019e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1020e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String[] getDisplayedValues() { 1021e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mDisplayedValues; 1022e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1023e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1024e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1025e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the values to be displayed. 1026e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1027e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param displayedValues The displayed values. 1028e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1029e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setDisplayedValues(String[] displayedValues) { 1030e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mDisplayedValues == displayedValues) { 1031e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1032e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1033e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mDisplayedValues = displayedValues; 1034e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mDisplayedValues != null) { 1035e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov // Allow text entry rather than strictly numeric entry. 1036e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT 1037e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); 1038e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } else { 1039e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 1040e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1041e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1042e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 1043206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1044206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1045206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1046206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getTopFadingEdgeStrength() { 1047206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 1048206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1049206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1050206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1051206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getBottomFadingEdgeStrength() { 1052206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 1053206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1054206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1055206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 10569cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov protected void onAttachedToWindow() { 10579cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov super.onAttachedToWindow(); 10589cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // make sure we show the controls only the very 10599cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // first time the user sees this widget 10604fd9dae6a23a22142f73749c291c9fd18459e381Svetoslav Ganov if (mFlingable && !isInEditMode()) { 10619cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // animate a bit slower the very first time 10629cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration * 2); 10639cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 10649cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 10659cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 10669cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov @Override 1067206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDetachedFromWindow() { 1068206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 1069206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1070206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1071206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1072206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void dispatchDraw(Canvas canvas) { 1073206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // There is a good reason for doing this. See comments in draw(). 1074206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1075206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1076206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1077206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void draw(Canvas canvas) { 1078206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Dispatch draw to our children only if we are not currently running 1079206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // the animation for simultaneously fading out the scroll wheel and 1080206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // showing in the buttons. This class takes advantage of the View 1081206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // implementation of fading edges effect to draw the selector wheel. 1082206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // However, in View.draw(), the fading is applied after all the children 1083206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // have been drawn and we do not want this fading to be applied to the 1084206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // buttons which are currently showing in. Therefore, we draw our 10859cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // children after we have completed drawing ourselves. 1086c75ec3324e9e3e6500148cc2978caab90ea962e4Chet Haase super.draw(canvas); 1087206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1088206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Draw our children if we are not showing the selector wheel of fading 1089206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // it out 1090206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mShowInputControlsAnimator.isRunning() || !mDrawSelectorWheel) { 1091206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov long drawTime = getDrawingTime(); 1092206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0, count = getChildCount(); i < count; i++) { 1093206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov View child = getChildAt(i); 1094206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!child.isShown()) { 1095206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov continue; 1096206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1097206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov drawChild(canvas, getChildAt(i), drawTime); 1098206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1099206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1100206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1101206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1102206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1103206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDraw(Canvas canvas) { 1104206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // we only draw the selector wheel 1105206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mDrawSelectorWheel) { 1106206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1107206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1108206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float x = (mRight - mLeft) / 2; 1109206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float y = mCurrentScrollOffset; 1110206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 11119cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the selector wheel 1112206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 1113206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length; i++) { 1114206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = selectorIndices[i]; 1115206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex); 1116206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov canvas.drawText(scrollSelectorValue, x, y, mSelectorPaint); 1117206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov y += mSelectorElementHeight; 1118206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 11199cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 11209cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the selection dividers (only if scrolling and drawable specified) 11219cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mSelectionDivider != null) { 11229cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setAlpha(mSelectorPaint.getAlpha()); 11239cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the top divider 11249cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int topOfTopDivider = 11259cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov (getHeight() - mSelectorElementHeight - mSelectionDividerHeight) / 2; 11269cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int bottomOfTopDivider = topOfTopDivider + mSelectionDividerHeight; 11279cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setBounds(0, topOfTopDivider, mRight, bottomOfTopDivider); 11289cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.draw(canvas); 11299cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 11309cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the bottom divider 11319cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int topOfBottomDivider = topOfTopDivider + mSelectorElementHeight; 11329cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int bottomOfBottomDivider = bottomOfTopDivider + mSelectorElementHeight; 11339cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setBounds(0, topOfBottomDivider, mRight, bottomOfBottomDivider); 11349cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.draw(canvas); 11359cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1137fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 113868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1139a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov * Resets the selector indices and clear the cached 1140a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov * string representation of these indices. 1141a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov */ 1142e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private void resetSelectorWheelIndices() { 1143a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov mSelectorIndexToStringCache.clear(); 1144a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov int[] selectorIdices = getSelectorIndices(); 1145a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov for (int i = 0; i < selectorIdices.length; i++) { 1146a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov selectorIdices[i] = Integer.MIN_VALUE; 1147a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1148a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1149a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov 1150a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov /** 1151206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets the current value of this NumberPicker, and sets mPrevious to the 1152206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * previous value. If current is greater than mEnd less than mStart, the 1153206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * value of mCurrent is wrapped around. Subclasses can override this to 1154206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * change the wrapping behavior 115568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 115668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * @param current the new value of the NumberPicker 115768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1158206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void changeCurrent(int current) { 1159e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mValue == current) { 1160206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1161206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wrap around the values if we go past the start or end 1163e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1164206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov current = getWrappedSelectorIndex(current); 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1166e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int previous = mValue; 1167e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setValue(current); 1168206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov notifyChange(previous, current); 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1170fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 117168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1172206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets the <code>alpha</code> of the {@link Paint} for drawing the selector 1173206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * wheel. 117468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1175206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @SuppressWarnings("unused") 1176206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Called by ShowInputControlsAnimator via reflection 1177206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setSelectorPaintAlpha(int alpha) { 1178206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint.setAlpha(alpha); 1179206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDrawSelectorWheel) { 1180206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 118468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 118558f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov * @return If the <code>event</code> is in the <code>view</code>. 118668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 118758f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov private boolean isEventInViewHitRect(MotionEvent event, View view) { 118858f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov view.getHitRect(mTempRect); 1189206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mTempRect.contains((int) event.getX(), (int) event.getY()); 1190206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1191206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1192206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1193206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets if to <code>drawSelectionWheel</code>. 1194206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1195206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setDrawSelectorWheel(boolean drawSelectorWheel) { 1196206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDrawSelectorWheel = drawSelectorWheel; 1197206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // do not fade if the selector wheel not shown 1198206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setVerticalFadingEdgeEnabled(drawSelectorWheel); 1199206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1200206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 12019cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void initializeScrollWheel() { 12029cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mInitialScrollOffset != Integer.MIN_VALUE) { 12039cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov return; 12049cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 12059cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12069cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 12079cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int totalTextHeight = selectorIndices.length * mTextSize; 120801fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov float totalTextGapHeight = (mBottom - mTop) - totalTextHeight; 120901fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov float textGapCount = selectorIndices.length - 1; 121001fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov int selectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f); 121101fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov // Compensate if text size is odd since every time we get its middle a pixel is lost. 121201fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov mInitialScrollOffset = mCurrentScrollOffset = mTextSize - (3 * (mTextSize % 2)); 12139cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectorElementHeight = mTextSize + selectorTextGapHeight; 12149cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov updateInputTextView(); 12159cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 1217206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1218206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Callback invoked upon completion of a given <code>scroller</code>. 1219206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1220206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void onScrollerFinished(Scroller scroller) { 1221206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller == mFlingScroller) { 1222206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(0); 12239cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1225206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 12269cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1230206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 12319cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * Handles transition to a given <code>scrollState</code> 123250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 12339cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void onScrollStateChange(int scrollState) { 12349cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mScrollState == scrollState) { 12359cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov return; 12369cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12379cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mScrollState = scrollState; 12389cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mOnScrollListener != null) { 12394bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mOnScrollListener.onScrollStateChange(this, scrollState); 124050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 124150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 124250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 124350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 1244206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flings the selector with the given <code>velocityY</code>. 1245206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1246206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void fling(int velocityY) { 1247206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 1248206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller flingScroller = mFlingScroller; 1249206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1250e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1251206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (velocityY > 0) { 1252206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1253206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1254206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1255206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1256206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1257206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (velocityY > 0) { 1258e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int maxY = mTextSize * (mValue - mMinValue); 1259206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, maxY); 1260206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1261e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int startY = mTextSize * (mMaxValue - mValue); 1262206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int maxY = startY; 1263206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, startY, 0, velocityY, 0, 0, 0, maxY); 12642bf761c20253222a763bce9a63d14c48ab08a556Suchi Amalapurapu } 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1266206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1267206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1270206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1271206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Hides the input controls which is the up/down arrows and the text field. 1272206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1273206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void hideInputControls() { 1274206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.cancel(); 1275206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(INVISIBLE); 1276206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(INVISIBLE); 1277206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setVisibility(INVISIBLE); 1278206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1279c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1280206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1281206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Show the input controls by making them visible and animating the alpha 1282206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * property up/down arrows. 12839cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * 12849cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * @param animationDuration The duration of the animation. 1285206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 12869cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void showInputControls(long animationDuration) { 1287206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 1288206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setVisibility(VISIBLE); 12899cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mShowInputControlsAnimator.setDuration(animationDuration); 1290206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.start(); 1291206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1292c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1293206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1294206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the visibility state of the increment and decrement buttons. 1295206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1296206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void updateIncrementAndDecrementButtonsVisibilityState() { 1297e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel || mValue < mMaxValue) { 1298206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(VISIBLE); 1299206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1300206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(INVISIBLE); 1301206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1302e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel || mValue > mMinValue) { 1303206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(VISIBLE); 1304206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1305206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(INVISIBLE); 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1310206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selector indices array with proper values with the current as 1311206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * the middle one. 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1313206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int[] getSelectorIndices() { 1314e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int current = getValue(); 1315206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] != current) { 1316206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < mSelectorIndices.length; i++) { 1317206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX); 1318e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1319206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndex = getWrappedSelectorIndex(selectorIndex); 1320206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1321206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorIndices[i] = selectorIndex; 1322206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(mSelectorIndices[i]); 1323206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1324206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1325206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mSelectorIndices; 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1327fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 132868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1329206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The wrapped index <code>selectorIndex</code> value. 133068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1331206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getWrappedSelectorIndex(int selectorIndex) { 1332e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndex > mMaxValue) { 1333e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1; 1334e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } else if (selectorIndex < mMinValue) { 1335e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1; 1336206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1337206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return selectorIndex; 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1340206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1341206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Increments the <code>selectorIndices</code> whose string representations 1342206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1343206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1344206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void incrementScrollSelectorIndices(int[] selectorIndices) { 1345206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length - 1; i++) { 1346206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i + 1]; 1347206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1348206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[selectorIndices.length - 2] + 1; 1349e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel && nextScrollSelectorIndex > mMaxValue) { 1350e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov nextScrollSelectorIndex = mMinValue; 1351206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1352206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[selectorIndices.length - 1] = nextScrollSelectorIndex; 1353206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1354206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1355fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1356206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1357206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Decrements the <code>selectorIndices</code> whose string representations 1358206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1359206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1360206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void decrementSelectorIndices(int[] selectorIndices) { 1361206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = selectorIndices.length - 1; i > 0; i--) { 1362206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i - 1]; 1363206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1364206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[1] - 1; 1365e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel && nextScrollSelectorIndex < mMinValue) { 1366e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov nextScrollSelectorIndex = mMaxValue; 1367206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1368206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[0] = nextScrollSelectorIndex; 1369206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1370206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1371fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1372206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1373206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensures we have a cached string representation of the given <code> 1374206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * selectorIndex</code> 1375206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * to avoid multiple instantiations of the same string. 1376206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1377206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void ensureCachedScrollSelectorValue(int selectorIndex) { 1378206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov SparseArray<String> cache = mSelectorIndexToStringCache; 1379206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = cache.get(selectorIndex); 1380206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scrollSelectorValue != null) { 1381206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1382206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1383e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndex < mMinValue || selectorIndex > mMaxValue) { 1384206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = ""; 1385206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1386206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues != null) { 1387e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int displayedValueIndex = selectorIndex - mMinValue; 138850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov scrollSelectorValue = mDisplayedValues[displayedValueIndex]; 1389206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1390206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = formatNumber(selectorIndex); 13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1393206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov cache.put(selectorIndex, scrollSelectorValue); 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1395fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1396206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private String formatNumber(int value) { 1397e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return (mFormatter != null) ? mFormatter.format(value) : String.valueOf(value); 1398206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1400206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void validateInputTextView(View v) { 1401206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(((TextView) v).getText()); 1402206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(str)) { 1403206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Restore to the old value as we don't allow empty values 1404206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 1405206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1406206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Check the new value and ensure it's in range 1407206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int current = getSelectedPos(str.toString()); 1408206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(current); 14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1410206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1411fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1412206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1413206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the view of this NumberPicker. If displayValues were specified in 14149cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * the string corresponding to the index specified by the current value will 14159cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * be returned. Otherwise, the formatter specified in {@link #setFormatter} 14169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * will be used to format the number. 1417206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1418206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void updateInputTextView() { 1419206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1420206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * If we don't have displayed values then use the current number else 1421206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * find the correct value in the displayed values for the current 1422206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * number. 1423206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1424206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 1425e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setText(formatNumber(mValue)); 1426206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1427e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setText(mDisplayedValues[mValue - mMinValue]); 14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mInputText.getText().length()); 1430206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1431fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1432206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1433206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Notifies the listener, if registered, of a change of the value of this 1434206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * NumberPicker. 1435206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1436206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void notifyChange(int previous, int current) { 1437cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov if (mOnValueChangeListener != null) { 1438cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mOnValueChangeListener.onValueChange(this, previous, mValue); 1439206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1440206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1442206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1443206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts a command for updating the current value every <code>updateMillis 1444206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * </code>. 1445206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1446206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postUpdateValueFromLongPress(int updateMillis) { 1447206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 1448206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 1449206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mUpdateFromLongPressCommand == null) { 1450206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateFromLongPressCommand = new UpdateValueFromLongPressCommand(); 1451206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1452206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateFromLongPressCommand.setUpdateStep(updateMillis); 1453206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mUpdateFromLongPressCommand); 1454206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1456206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1457206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Removes all pending callback from the message queue. 1458206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1459206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void removeAllCallbacks() { 1460206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mUpdateFromLongPressCommand != null) { 1461206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mUpdateFromLongPressCommand); 1462206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1463206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerCommand != null) { 1464206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mAdjustScrollerCommand); 1465206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1466206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand != null) { 1467206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1471206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1472206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selected index given its displayed <code>value</code>. 1473206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1474206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getSelectedPos(String value) { 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisplayedValues == null) { 1476aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy try { 1477206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 1478aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } catch (NumberFormatException e) { 1479206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 1480aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mDisplayedValues.length; i++) { 1483206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Don't force the user to type in jan when ja will do 1484206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov value = value.toLowerCase(); 1485206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues[i].toLowerCase().startsWith(value)) { 1486e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue + i; 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1489fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1490206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1491206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The user might have typed in a number into the month field i.e. 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10 instead of OCT so support that too. 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1495206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 1497fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1498206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1501e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue; 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1505206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link SetSelectionCommand} from the given <code>selectionStart 1506206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * </code> to 1507206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * <code>selectionEnd</code>. 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1509206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postSetSelectionCommand(int selectionStart, int selectionEnd) { 1510206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand == null) { 1511206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand = new SetSelectionCommand(); 1512206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1513206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 1514206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1515206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionStart = selectionStart; 1516206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionEnd = selectionEnd; 1517206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mSetSelectionCommand); 15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 151968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 152068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1521206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link AdjustScrollerCommand} within the given <code> 1522206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * delayMillis</code> 1523206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * . 152468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1525206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postAdjustScrollerCommand(int delayMillis) { 1526206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerCommand == null) { 1527206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerCommand = new AdjustScrollerCommand(); 1528206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1529206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mAdjustScrollerCommand); 1530206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1531206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postDelayed(mAdjustScrollerCommand, delayMillis); 153268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 153368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 153468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1535206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Filter for accepting only valid indices or prefixes of the string 1536206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * representation of valid indices. 153768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1538206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class InputTextFilter extends NumberKeyListener { 1539206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1540206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // XXX This doesn't allow for range limits when controlled by a 1541206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // soft input method! 1542206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public int getInputType() { 1543206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return InputType.TYPE_CLASS_TEXT; 1544206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1545206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1546206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1547206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected char[] getAcceptedChars() { 1548206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return DIGIT_CHARACTERS; 1549206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1550206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1551206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1552206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public CharSequence filter(CharSequence source, int start, int end, Spanned dest, 1553206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int dstart, int dend) { 1554206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 1555206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = super.filter(source, start, end, dest, dstart, dend); 1556206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (filtered == null) { 1557206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov filtered = source.subSequence(start, end); 1558206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1559206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1560206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 1561206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 1562206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1563206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ("".equals(result)) { 1564206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return result; 1565206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1566206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int val = getSelectedPos(result); 1567206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1568206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1569206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensure the user can't type in a value greater than the max 1570206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * allowed. We have to allow less than min as the user might 1571206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * want to delete some numbers and then type a new number. 1572206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1573e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (val > mMaxValue) { 1574206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1575206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1576206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return filtered; 1577206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1578206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1579206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = String.valueOf(source.subSequence(start, end)); 1580206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(filtered)) { 1581206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1582206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1583206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 1584206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 1585206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(result).toLowerCase(); 1586206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (String val : mDisplayedValues) { 1587206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String valLowerCase = val.toLowerCase(); 1588206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (valLowerCase.startsWith(str)) { 1589206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postSetSelectionCommand(result.length(), val.length()); 1590206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return val.subSequence(dstart, val.length()); 1591206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1592206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1593206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1594206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1595206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1596206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1597206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1598206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1599206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for setting the input text selection. 1600206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1601206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class SetSelectionCommand implements Runnable { 1602206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionStart; 1603206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1604206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionEnd; 1605206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1606206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1607206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mSelectionStart, mSelectionEnd); 1608206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1609206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1610206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1611206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1612206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for adjusting the scroller to show in its center the closest of 1613206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * the displayed items. 1614206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1615206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class AdjustScrollerCommand implements Runnable { 1616206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1617206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 161834c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (mInitialScrollOffset == mCurrentScrollOffset) { 161934c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov updateInputTextView(); 16209cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 162134c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov return; 162234c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov } 162334c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov // adjust to the closest value 1624206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaY = mInitialScrollOffset - mCurrentScrollOffset; 162534c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (Math.abs(deltaY) > mSelectorElementHeight / 2) { 162634c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov deltaY += (deltaY > 0) ? -mSelectorElementHeight : mSelectorElementHeight; 162734c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov } 16289cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mAdjustScroller.startScroll(0, 0, 0, deltaY, SELECTOR_ADJUSTMENT_DURATION_MILLIS); 1629206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 1630206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1631206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1632206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1633206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1634206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for updating the current value from a long press. 1635206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1636206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class UpdateValueFromLongPressCommand implements Runnable { 1637206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mUpdateStep = 0; 1638206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1639206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setUpdateStep(int updateStep) { 1640206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateStep = updateStep; 1641206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1642206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1643206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1644e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov changeCurrent(mValue + mUpdateStep); 16454bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov postDelayed(this, mLongPressUpdateInterval); 1646206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 164768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 16487762d93621f508f4410fd37b5bbdfec0071b0420Paul Westbrook} 1649