NumberPicker.java revision a53efe9923bedab4fe5d578f32eaff308e5b9e76
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; 513fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 523fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganovimport android.view.accessibility.AccessibilityManager; 539cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganovimport android.view.animation.DecelerateInterpolator; 54206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.inputmethod.InputMethodManager; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook/** 574bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * A widget that enables the user to select a number form a predefined range. 584bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * The widget presents an input filed and up and down buttons for selecting the 594bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * current value. Pressing/long pressing the up and down buttons increments and 604bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * decrements the current value respectively. Touching the input filed shows a 614bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * scroll wheel, tapping on which while shown and not moving allows direct edit 624bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * of the current value. Sliding motions up or down hide the buttons and the 634bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * input filed, show the scroll wheel, and rotate the latter. Flinging is 644bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * also supported. The widget enables mapping from positions to strings such 654bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * that instead the position index the corresponding string is displayed. 664bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 674bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * For an example of using this widget, see {@link android.widget.TimePicker}. 684bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 6968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 7068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook@Widget 7168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrookpublic class NumberPicker extends LinearLayout { 72fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 7368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 74e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * The default update interval during long press. 75e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 76e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private static final long DEFAULT_LONG_PRESS_UPDATE_INTERVAL = 300; 77e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 78e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 79206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The index of the middle selector item. 8068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 81206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_MIDDLE_ITEM_INDEX = 2; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 84206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The coefficient by which to adjust (divide) the max fling velocity. 8568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 86206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT = 8; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 88206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 89206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The the duration for adjusting the selector wheel. 90206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 91206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_ADJUSTMENT_DURATION_MILLIS = 800; 92fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 93206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 94206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The the delay for showing the input controls after a single tap on the 95206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * input text. 96206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 97206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SHOW_INPUT_CONTROLS_DELAY_MILLIS = ViewConfiguration 98206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov .getDoubleTapTimeout(); 99206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 100206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 101206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The update step for incrementing the current value. 102206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 103206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int UPDATE_STEP_INCREMENT = 1; 104206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 105206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 106206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The update step for decrementing the current value. 107206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 108206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int UPDATE_STEP_DECREMENT = -1; 109206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 110206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 111206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The strength of fading in the top and bottom while drawing the selector. 112206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 113206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final float TOP_AND_BOTTOM_FADING_EDGE_STRENGTH = 0.9f; 114206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 115206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * The default unscaled height of the selection divider. 1179cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 1189cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final int UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT = 2; 1199cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 1209cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 121206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The numbers accepted by the input text's {@link Filter} 122206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 123206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final char[] DIGIT_CHARACTERS = new char[] { 124206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 125206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 126206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 127206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 128206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Use a custom NumberPicker formatting callback to use two-digit minutes 129206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * strings like "01". Keeping a static formatter etc. is the most efficient 130206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * way to do this; it avoids creating temporary objects on every call to 131206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * format(). 132e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 133e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @hide 134206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 135206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() { 136206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final StringBuilder mBuilder = new StringBuilder(); 137206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 138f0ef665299d795df7905897e1c337e37891dafefJean-Baptiste Queru final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US); 139206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 140206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final Object[] mArgs = new Object[1]; 141206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 142e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String format(int value) { 143206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mArgs[0] = value; 144206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBuilder.delete(0, mBuilder.length()); 145206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mFmt.format("%02d", mArgs); 146206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mFmt.toString(); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 150206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 151206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The increment button. 152206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 153206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final ImageButton mIncrementButton; 154206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 155206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 156206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The decrement button. 157206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 158206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final ImageButton mDecrementButton; 159206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 160206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 161206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The text for showing the current value. 162206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 163206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final EditText mInputText; 164206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 165206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 166206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The height of the text. 167206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 168206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int mTextSize; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 170206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 171206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The values to be displayed instead the indices. 172206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] mDisplayedValues; 17468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 17568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 17668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Lower value of the range of numbers allowed for the NumberPicker 17768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 178e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mMinValue; 17968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 18068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 18168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Upper value of the range of numbers allowed for the NumberPicker 18268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 183e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mMaxValue; 18468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 18568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 18668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Current value of this NumberPicker 18768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 188e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mValue; 18968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 19068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 191206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Listener to be notified upon current value change. 19268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 193cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov private OnValueChangeListener mOnValueChangeListener; 19450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 19550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 19650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * Listener to be notified upon scroll state change. 19750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 19850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov private OnScrollListener mOnScrollListener; 199206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 200206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 201206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Formatter for for displaying the current value. 202206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Formatter mFormatter; 204fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 205206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 206206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The speed for updating the value form long press. 207206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 208e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private long mLongPressUpdateInterval = DEFAULT_LONG_PRESS_UPDATE_INTERVAL; 209fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 21068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 211206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Cache for the string representation of selector indices. 212206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 213206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final SparseArray<String> mSelectorIndexToStringCache = new SparseArray<String>(); 214206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 215206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 216206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The selector indices whose value are show by the selector. 217206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 218206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int[] mSelectorIndices = new int[] { 219206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, 220206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Integer.MIN_VALUE 221206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 222206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 223206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 224206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Paint} for drawing the selector. 225206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 226206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Paint mSelectorPaint; 227206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 228206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 229206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The height of a selector element (text + gap). 230206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 231206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectorElementHeight; 232206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 233206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 234206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The initial offset of the scroll selector. 235206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 236206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mInitialScrollOffset = Integer.MIN_VALUE; 237206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 238206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 239206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The current offset of the scroll selector. 240206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 241206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mCurrentScrollOffset; 242206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 243206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 244206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Scroller} responsible for flinging the selector. 245206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 246206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Scroller mFlingScroller; 247206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 248206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 249206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Scroller} responsible for adjusting the selector. 250206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 251206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Scroller mAdjustScroller; 252206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 253206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 254206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The previous Y coordinate while scrolling the selector. 255206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 256206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mPreviousScrollerY; 257206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 258206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 259206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for setting the input text selection. 260206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 261206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private SetSelectionCommand mSetSelectionCommand; 262206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 263206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 264206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for adjusting the scroller. 265206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 266206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private AdjustScrollerCommand mAdjustScrollerCommand; 267206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 268206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 269206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for updating the current value from long 270206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * press. 271206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 272206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private UpdateValueFromLongPressCommand mUpdateFromLongPressCommand; 273206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 274206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 275206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * {@link Animator} for showing the up/down arrows. 276206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 277206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final AnimatorSet mShowInputControlsAnimator; 278206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 279206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 280206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The Y position of the last down event. 281206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 282206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private float mLastDownEventY; 283206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 284206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 285206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The Y position of the last motion event. 286206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 287206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private float mLastMotionEventY; 288206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 289206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 290206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to begin edit on next up event. 291206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 292206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mBeginEditOnUpEvent; 293206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 294206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 295206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to adjust the selector wheel on next up event. 296206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 297206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mAdjustScrollerOnUpEvent; 298206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 299206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 300206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to draw the selector wheel. 301206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 302206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mDrawSelectorWheel; 303206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 304206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 305206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Determines speed during touch scrolling. 306206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 307206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private VelocityTracker mVelocityTracker; 308206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 309206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 310206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledTouchSlop() 311206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 312206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mTouchSlop; 313206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 314206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 315206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledMinimumFlingVelocity() 316206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 317206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mMinimumFlingVelocity; 318206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 319206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 320206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledMaximumFlingVelocity() 321206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 322206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mMaximumFlingVelocity; 323206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 324206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 325206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag whether the selector should wrap around. 326206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 327e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private boolean mWrapSelectorWheel; 328206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 329206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 330206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The back ground color used to optimize scroller fading. 33168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 332206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int mSolidColor; 333206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 334206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 3354243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov * Flag indicating if this widget supports flinging. 3364243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov */ 3374243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov private final boolean mFlingable; 3384243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 3394243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov /** 3409cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * Divider for showing item to be selected while scrolling 3419cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 3429cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final Drawable mSelectionDivider; 3439cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 3449cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 3459cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * The height of the selection divider. 3469cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 3479cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final int mSelectionDividerHeight; 3489cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 3499cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 350206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Reusable {@link Rect} instance. 351206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 352206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Rect mTempRect = new Rect(); 353206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 354206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 35550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The current scroll state of the number picker. 35650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 35750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE; 35850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 35950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 3609cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * The duration of the animation for showing the input controls. 3619cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 3629cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final long mShowInputControlsAnimimationDuration; 3639cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 3649cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 365e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface to listen for changes of the current value. 366206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 367cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov public interface OnValueChangeListener { 368e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 369206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 3704bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Called upon a change of the current value. 3714bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 372206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param picker The NumberPicker associated with this listener. 373206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param oldVal The previous value. 374206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param newVal The new value. 375206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 376e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov void onValueChange(NumberPicker picker, int oldVal, int newVal); 377206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 378206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 379206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 380e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface to listen for the picker scroll state. 38150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 38250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public interface OnScrollListener { 38350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 38450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 38550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The view is not scrolling. 38650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 38750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_IDLE = 0; 38850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 38950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 39050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The user is scrolling using touch, and their finger is still on the screen. 39150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 39250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_TOUCH_SCROLL = 1; 39350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 39450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 39550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The user had previously been scrolling using touch and performed a fling. 39650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 39750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_FLING = 2; 39850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 39950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 400e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Callback invoked while the number picker scroll state has changed. 40150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 402e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param view The view whose scroll state is being reported. 403e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param scrollState The current scroll state. One of 404e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_IDLE}, 405e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_TOUCH_SCROLL} or 406e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_IDLE}. 40750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 4084bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void onScrollStateChange(NumberPicker view, int scrollState); 40950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 41050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 41150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 412e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface used to format current value into a string for presentation. 413206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 414206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public interface Formatter { 4154bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 4164bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 417e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Formats a string representation of the current value. 4184bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 4194bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param value The currently selected value. 4204bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @return A formatted string representation. 4214bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 422e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String format(int value); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 424fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 42568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 4264bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Create a new number picker. 4274bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 4284bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param context The application environment. 4294bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 4304bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public NumberPicker(Context context) { 4314bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov this(context, null); 4324bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 4334bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 4344bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 4354bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Create a new number picker. 436206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 437206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param context The application environment. 438206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param attrs A collection of attributes. 43968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public NumberPicker(Context context, AttributeSet attrs) { 441206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov this(context, attrs, R.attr.numberPickerStyle); 442206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 443206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 444206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 445206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Create a new number picker 446206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 447206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param context the application environment. 448206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param attrs a collection of attributes. 449206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param defStyle The default style to apply to this view. 450206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 451206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public NumberPicker(Context context, AttributeSet attrs, int defStyle) { 452206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov super(context, attrs, defStyle); 453206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 454206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // process style attributes 455206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov TypedArray attributesArray = context.obtainStyledAttributes(attrs, 456206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov R.styleable.NumberPicker, defStyle, 0); 457206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSolidColor = attributesArray.getColor(R.styleable.NumberPicker_solidColor, 0); 4584243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov mFlingable = attributesArray.getBoolean(R.styleable.NumberPicker_flingable, true); 4599cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider = attributesArray.getDrawable(R.styleable.NumberPicker_selectionDivider); 4609cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int defSelectionDividerHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4619cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT, 4629cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov getResources().getDisplayMetrics()); 4639cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDividerHeight = attributesArray.getDimensionPixelSize( 4649cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight); 465206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov attributesArray.recycle(); 466206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 4679cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mShowInputControlsAnimimationDuration = getResources().getInteger( 4689cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov R.integer.config_longAnimTime); 4699cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 470206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // By default Linearlayout that we extend is not drawn. This is 471206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // its draw() method is not called but dispatchDraw() is called 472206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // directly (see ViewGroup.drawChild()). However, this class uses 473206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // the fading edge effect implemented by View and we need our 474206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // draw() method to be called. Therefore, we declare we will draw. 475206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setWillNotDraw(false); 4763fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov setDrawScrollWheel(false); 477206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 478206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( 479206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Context.LAYOUT_INFLATER_SERVICE); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inflater.inflate(R.layout.number_picker, this, true); 48168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 482206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov OnClickListener onClickListener = new OnClickListener() { 48368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook public void onClick(View v) { 484206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 485206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (v.getId() == R.id.increment) { 486e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov changeCurrent(mValue + 1); 487206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 488e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov changeCurrent(mValue - 1); 48968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 49068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 49168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook }; 49268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 493206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov OnLongClickListener onLongClickListener = new OnLongClickListener() { 494206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onLongClick(View v) { 495206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 496206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (v.getId() == R.id.increment) { 497206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postUpdateValueFromLongPress(UPDATE_STEP_INCREMENT); 498206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 499206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postUpdateValueFromLongPress(UPDATE_STEP_DECREMENT); 500206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 501206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 502206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 503206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 50468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 505206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // increment button 506206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton = (ImageButton) findViewById(R.id.increment); 507206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setOnClickListener(onClickListener); 508206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setOnLongClickListener(onLongClickListener); 509206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 510206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // decrement button 511206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton = (ImageButton) findViewById(R.id.decrement); 512206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setOnClickListener(onClickListener); 513206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setOnLongClickListener(onLongClickListener); 514206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 515206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // input text 516012dd5a461f18a2e5dad38c60282fac1c21ff7feSvetoslav Ganov mInputText = (EditText) findViewById(R.id.numberpicker_input); 517206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setOnFocusChangeListener(new OnFocusChangeListener() { 518206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onFocusChange(View v, boolean hasFocus) { 519a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov if (hasFocus) { 520a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov mInputText.selectAll(); 521a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov } else { 522a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov mInputText.setSelection(0, 0); 523206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov validateInputTextView(v); 52468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 52568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 526206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 527206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setFilters(new InputFilter[] { 528206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov new InputTextFilter() 529206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 53068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 531206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 532206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 533206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // initialize constants 534206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTouchSlop = ViewConfiguration.getTapTimeout(); 535206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ViewConfiguration configuration = ViewConfiguration.get(context); 536206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTouchSlop = configuration.getScaledTouchSlop(); 537206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); 538206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity() 539206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov / SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT; 540206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTextSize = (int) mInputText.getTextSize(); 541206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 542206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the selector wheel paint 543206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Paint paint = new Paint(); 544206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setAntiAlias(true); 545206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTextAlign(Align.CENTER); 546206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTextSize(mTextSize); 547206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTypeface(mInputText.getTypeface()); 548206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ColorStateList colors = mInputText.getTextColors(); 549206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int color = colors.getColorForState(ENABLED_STATE_SET, Color.WHITE); 550206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setColor(color); 551206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint = paint; 552206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 553206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the animator for showing the input controls 554206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ValueAnimator fadeScroller = ObjectAnimator.ofInt(this, "selectorPaintAlpha", 255, 0); 555206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ObjectAnimator showIncrementButton = ObjectAnimator.ofFloat(mIncrementButton, 556206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov "alpha", 0, 1); 557206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ObjectAnimator showDecrementButton = ObjectAnimator.ofFloat(mDecrementButton, 558206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov "alpha", 0, 1); 559206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator = new AnimatorSet(); 560206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.playTogether(fadeScroller, showIncrementButton, 5615203194fdff0c0aaefc405d65871ef0e06e7c682Svetoslav Ganov showDecrementButton); 562206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.addListener(new AnimatorListenerAdapter() { 563206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mCanceled = false; 564206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 565206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 566206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onAnimationEnd(Animator animation) { 567206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mCanceled) { 568206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // if canceled => we still want the wheel drawn 5693fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov setDrawScrollWheel(false); 57068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 571206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCanceled = false; 572206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint.setAlpha(255); 573206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 57468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 57568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 576206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 577206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onAnimationCancel(Animator animation) { 578206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mShowInputControlsAnimator.isRunning()) { 579206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCanceled = true; 580206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 581206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 582206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 58368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 584206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the fling and adjust scrollers 585bf80562d22b2bbe7944d80d0524c69d0238010cbSvetoslav Ganov mFlingScroller = new Scroller(getContext(), null, true); 5869cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mAdjustScroller = new Scroller(getContext(), new DecelerateInterpolator(2.5f)); 587fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 588206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 589206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 5909cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 5914fd9dae6a23a22142f73749c291c9fd18459e381Svetoslav Ganov if (mFlingable && !isInEditMode()) { 5929cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // Start with shown selector wheel and hidden controls. When made 5939cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // visible hide the selector and fade-in the controls to suggest 5949cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // fling interaction. 5953fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov setDrawScrollWheel(true); 5969cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov hideInputControls(); 5979cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 598206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 599206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 600206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 6019cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 6029cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov super.onLayout(changed, left, top, right, bottom); 6039cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // need to do this when we know our size 6049cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov initializeScrollWheel(); 605206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 606206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 607206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 608206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onInterceptTouchEvent(MotionEvent event) { 6094243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov if (!isEnabled() || !mFlingable) { 61051c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return false; 61151c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 612206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (event.getActionMasked()) { 613206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_DOWN: 614206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mLastMotionEventY = mLastDownEventY = event.getY(); 615206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 616092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov mShowInputControlsAnimator.cancel(); 617206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 618206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = true; 619206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDrawSelectorWheel) { 62050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov boolean scrollersFinished = mFlingScroller.isFinished() 621206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov && mAdjustScroller.isFinished(); 62250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (!scrollersFinished) { 62350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mFlingScroller.forceFinished(true); 62450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mAdjustScroller.forceFinished(true); 6259cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 62650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 62750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mBeginEditOnUpEvent = scrollersFinished; 628206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = true; 629092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 630206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 631206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 63258f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov if (isEventInViewHitRect(event, mInputText) 63358f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov || (!mIncrementButton.isShown() 63458f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && isEventInViewHitRect(event, mIncrementButton)) 63558f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov || (!mDecrementButton.isShown() 63658f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && isEventInViewHitRect(event, mDecrementButton))) { 637206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = false; 6383fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov setDrawScrollWheel(true); 639092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 640206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 641206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 642206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 643206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_MOVE: 644206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float currentMoveY = event.getY(); 645206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 646206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 647206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 6489cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 6493fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov setDrawScrollWheel(true); 650092bda57c4b8caad378400b2bc97b9ac66fd2179Svetoslav Ganov hideInputControls(); 651206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 652206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 653206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 654206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 655206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return false; 656206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 657206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 658206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 659206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onTouchEvent(MotionEvent ev) { 66051c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov if (!isEnabled()) { 66151c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return false; 66251c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 663206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mVelocityTracker == null) { 664206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = VelocityTracker.obtain(); 665206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 666206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.addMovement(ev); 667206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = ev.getActionMasked(); 668206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (action) { 669206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_MOVE: 670206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float currentMoveY = ev.getY(); 67150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (mBeginEditOnUpEvent 67250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov || mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 673206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 674206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 675206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 6769cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 677206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 678206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 679206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaMoveY = (int) (currentMoveY - mLastMotionEventY); 680206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, deltaMoveY); 681206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 682206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mLastMotionEventY = currentMoveY; 683206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 684206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_UP: 685206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mBeginEditOnUpEvent) { 6863fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov setDrawScrollWheel(false); 6879cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 688206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.requestFocus(); 689206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov InputMethodManager imm = (InputMethodManager) getContext().getSystemService( 690206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Context.INPUT_METHOD_SERVICE); 691206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov imm.showSoftInput(mInputText, 0); 692206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 693206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 694206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov VelocityTracker velocityTracker = mVelocityTracker; 695206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); 696206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int initialVelocity = (int) velocityTracker.getYVelocity(); 697206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (Math.abs(initialVelocity) > mMinimumFlingVelocity) { 698206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov fling(initialVelocity); 6999cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); 700206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 701206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerOnUpEvent) { 702206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mFlingScroller.isFinished() && mAdjustScroller.isFinished()) { 703206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(0); 704206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 705206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 706206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(SHOW_INPUT_CONTROLS_DELAY_MILLIS); 707206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 708206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 709206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.recycle(); 710206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = null; 711206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 712206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 713206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 714206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 715206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 716206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 717206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTouchEvent(MotionEvent event) { 718206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = event.getActionMasked(); 719206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ((action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) 72058f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov && !isEventInViewHitRect(event, mInputText)) { 721206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 722206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 723206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTouchEvent(event); 724206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 725206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 726206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 727206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchKeyEvent(KeyEvent event) { 728206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int keyCode = event.getKeyCode(); 729206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) { 730206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 731206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 732206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchKeyEvent(event); 733206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 734206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 735206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 736206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTrackballEvent(MotionEvent event) { 737206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = event.getActionMasked(); 738206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 739206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 740206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 741206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTrackballEvent(event); 742206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 744206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 745206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void computeScroll() { 746206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mDrawSelectorWheel) { 747206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 748206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 749206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller scroller = mFlingScroller; 750206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 751206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller = mAdjustScroller; 752206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 753206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 754206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 755206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 756206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller.computeScrollOffset(); 757206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int currentScrollerY = scroller.getCurrY(); 758206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mPreviousScrollerY == 0) { 759206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = scroller.getStartY(); 760206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 761206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, currentScrollerY - mPreviousScrollerY); 762206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = currentScrollerY; 763206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 764206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov onScrollerFinished(scroller); 765206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 766206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 769fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setEnabled(boolean enabled) { 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setEnabled(enabled); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIncrementButton.setEnabled(enabled); 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDecrementButton.setEnabled(enabled); 775206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setEnabled(enabled); 776206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 777206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 778206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 779206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void scrollBy(int x, int y) { 780206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 78134c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (!mWrapSelectorWheel && y > 0 78234c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { 783206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 784206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 785206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 78634c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (!mWrapSelectorWheel && y < 0 78734c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { 788206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 789206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 790206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 791206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += y; 7926c742f1e95dfe1f808bf02fadd5fbf9660b95050Svetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset >= mSelectorElementHeight) { 793206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset -= mSelectorElementHeight; 794206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov decrementSelectorIndices(selectorIndices); 795206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); 796e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { 797206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 798206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 799206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 8006c742f1e95dfe1f808bf02fadd5fbf9660b95050Svetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset <= -mSelectorElementHeight) { 801206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += mSelectorElementHeight; 802206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov incrementScrollSelectorIndices(selectorIndices); 803206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); 804e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { 805206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 806206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 807206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 809fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 8104bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov @Override 8114bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public int getSolidColor() { 8124bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov return mSolidColor; 8134bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 8144bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 81568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 8164bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the listener to be notified on change of the current value. 817206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 818e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param onValueChangedListener The listener. 81968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 820cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov public void setOnValueChangedListener(OnValueChangeListener onValueChangedListener) { 821cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mOnValueChangeListener = onValueChangedListener; 82250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 82350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 82450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 8254bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set listener to be notified for scroll state changes. 82650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 827e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param onScrollListener The listener. 82850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 82950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public void setOnScrollListener(OnScrollListener onScrollListener) { 83050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mOnScrollListener = onScrollListener; 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 832fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 83368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 8344bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set the formatter to be used for formatting the current value. 8354bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 836e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Note: If you have provided alternative values for the values this 837e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * formatter is never invoked. 8384bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 839206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 840e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param formatter The formatter object. If formatter is <code>null</code>, 841e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link String#valueOf(int)} will be used. 8424bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 843e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setDisplayedValues(String[]) 84468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFormatter(Formatter formatter) { 846e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (formatter == mFormatter) { 847e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 848e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFormatter = formatter; 850e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 8519cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov updateInputTextView(); 852206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 853206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 854206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 855e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Set the current value for the number picker. 8564bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 857e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMinValue()} and 858e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the 859e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMinValue()} value. 860e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 861e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 862e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMinValue()} and 863e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the 864e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMaxValue()} value. 865e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 866e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 867e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMaxValue()} and 868e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the 869e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMaxValue()} value. 870e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 871e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 872e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMaxValue()} and 873e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the 874e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMinValue()} value. 8754bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 876206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 877e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param value The current value. 8784bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @see #setWrapSelectorWheel(boolean) 879e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setMinValue(int) 880e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setMaxValue(int) 881206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 882e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setValue(int value) { 883e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mValue == value) { 884a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov return; 885a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 886e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (value < mMinValue) { 887e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov value = mWrapSelectorWheel ? mMaxValue : mMinValue; 888206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 889e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (value > mMaxValue) { 890e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov value = mWrapSelectorWheel ? mMinValue : mMaxValue; 8918bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powell } 892e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = value; 893e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 894e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 896fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 89768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 898e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Gets whether the selector wheel wraps when reaching the min/max value. 89968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 900e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return True if the selector wheel wraps. 9014bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 902e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #getMinValue() 903e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #getMaxValue() 90468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 905e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public boolean getWrapSelectorWheel() { 906e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mWrapSelectorWheel; 907206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 908206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 909206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 910e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets whether the selector wheel shown during flinging/scrolling should 911e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * wrap around the {@link NumberPicker#getMinValue()} and 912e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getMaxValue()} values. 913e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 914e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * By default if the range (max - min) is more than five (the number of 915e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * items shown on the selector wheel) the selector wheel wrapping is 916e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * enabled. 917e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 918206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 919206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param wrapSelector Whether to wrap. 920206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 9214bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setWrapSelectorWheel(boolean wrapSelector) { 922e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (wrapSelector && (mMaxValue - mMinValue) < mSelectorIndices.length) { 923206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov throw new IllegalStateException("Range less than selector items count."); 924206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 925e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (wrapSelector != mWrapSelectorWheel) { 926206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // force the selector indices array to be reinitialized 927206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] = Integer.MAX_VALUE; 928e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mWrapSelectorWheel = wrapSelector; 929156f20919b3d5f298f8851215adbf65f8b4dc61bSvetoslav Ganov // force redraw since we might look different 930156f20919b3d5f298f8851215adbf65f8b4dc61bSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 931206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9354bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the speed at which the numbers be incremented and decremented when 9364bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * the up and down buttons are long pressed respectively. 937e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 938e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * The default value is 300 ms. 939e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 94068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 9414bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param intervalMillis The speed (in milliseconds) at which the numbers 942e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * will be incremented and decremented. 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9444bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setOnLongPressUpdateInterval(long intervalMillis) { 9454bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mLongPressUpdateInterval = intervalMillis; 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 947fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 948206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 949e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the value of the picker. 950e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 951e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The value. 952e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 953e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getValue() { 954e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mValue; 955e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 956e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 957e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 958e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the min value of the picker. 959e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 960e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The min value 961e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 962e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getMinValue() { 963e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue; 964e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 965e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 966e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 967e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the min value of the picker. 968206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 969e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param minValue The min value. 970206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 971e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setMinValue(int minValue) { 972e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMinValue == minValue) { 973e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 974e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 975e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (minValue < 0) { 976e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov throw new IllegalArgumentException("minValue must be >= 0"); 977e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 978e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinValue = minValue; 979e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMinValue > mValue) { 980e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = mMinValue; 981e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 982e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; 983e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 984e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 985e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 986206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 987206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 9884bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 989e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the max value of the picker. 9904bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 991e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The max value. 9924bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 993e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getMaxValue() { 994e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMaxValue; 9954bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 9964bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 9974bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 998e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the max value of the picker. 9994bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 1000e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param maxValue The max value. 10014bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 1002e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setMaxValue(int maxValue) { 1003e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMaxValue == maxValue) { 1004e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1005e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1006e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (maxValue < 0) { 1007e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov throw new IllegalArgumentException("maxValue must be >= 0"); 1008e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1009e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMaxValue = maxValue; 1010e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMaxValue < mValue) { 1011e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = mMaxValue; 1012e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1013e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; 1014e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 1015e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 1016e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1017e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1018e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1019e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1020e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Gets the values to be displayed instead of string values. 1021e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1022e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The displayed values. 1023e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1024e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String[] getDisplayedValues() { 1025e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mDisplayedValues; 1026e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1027e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1028e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1029e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the values to be displayed. 1030e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1031e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param displayedValues The displayed values. 1032e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1033e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setDisplayedValues(String[] displayedValues) { 1034e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mDisplayedValues == displayedValues) { 1035e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1036e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1037e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mDisplayedValues = displayedValues; 1038e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mDisplayedValues != null) { 1039e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov // Allow text entry rather than strictly numeric entry. 1040e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT 1041e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); 1042e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } else { 1043e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 1044e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1045e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1046e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov resetSelectorWheelIndices(); 1047206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1048206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1049206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1050206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getTopFadingEdgeStrength() { 1051206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 1052206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1053206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1054206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1055206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getBottomFadingEdgeStrength() { 1056206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 1057206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1058206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1059206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 10609cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov protected void onAttachedToWindow() { 10619cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov super.onAttachedToWindow(); 10629cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // make sure we show the controls only the very 10639cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // first time the user sees this widget 10644fd9dae6a23a22142f73749c291c9fd18459e381Svetoslav Ganov if (mFlingable && !isInEditMode()) { 10659cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // animate a bit slower the very first time 10669cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration * 2); 10679cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 10689cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 10699cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 10709cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov @Override 1071206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDetachedFromWindow() { 1072206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 1073206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1074206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1075206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1076206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void dispatchDraw(Canvas canvas) { 1077206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // There is a good reason for doing this. See comments in draw(). 1078206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1079206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1080206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1081206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void draw(Canvas canvas) { 1082206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Dispatch draw to our children only if we are not currently running 1083206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // the animation for simultaneously fading out the scroll wheel and 1084206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // showing in the buttons. This class takes advantage of the View 1085206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // implementation of fading edges effect to draw the selector wheel. 1086206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // However, in View.draw(), the fading is applied after all the children 1087206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // have been drawn and we do not want this fading to be applied to the 1088206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // buttons which are currently showing in. Therefore, we draw our 10899cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // children after we have completed drawing ourselves. 1090c75ec3324e9e3e6500148cc2978caab90ea962e4Chet Haase super.draw(canvas); 1091206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1092206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Draw our children if we are not showing the selector wheel of fading 1093206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // it out 1094206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mShowInputControlsAnimator.isRunning() || !mDrawSelectorWheel) { 1095206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov long drawTime = getDrawingTime(); 1096206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0, count = getChildCount(); i < count; i++) { 1097206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov View child = getChildAt(i); 1098206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!child.isShown()) { 1099206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov continue; 1100206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1101206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov drawChild(canvas, getChildAt(i), drawTime); 1102206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1103206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1104206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1105206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1106206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1107206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDraw(Canvas canvas) { 1108206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // we only draw the selector wheel 1109206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mDrawSelectorWheel) { 1110206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1111206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1112206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float x = (mRight - mLeft) / 2; 1113206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float y = mCurrentScrollOffset; 1114206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 11159cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the selector wheel 1116206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 1117206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length; i++) { 1118206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = selectorIndices[i]; 1119206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex); 1120206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov canvas.drawText(scrollSelectorValue, x, y, mSelectorPaint); 1121206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov y += mSelectorElementHeight; 1122206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 11239cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 11249cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the selection dividers (only if scrolling and drawable specified) 11259cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mSelectionDivider != null) { 11269cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setAlpha(mSelectorPaint.getAlpha()); 11279cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the top divider 11289cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int topOfTopDivider = 11299cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov (getHeight() - mSelectorElementHeight - mSelectionDividerHeight) / 2; 11309cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int bottomOfTopDivider = topOfTopDivider + mSelectionDividerHeight; 11319cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setBounds(0, topOfTopDivider, mRight, bottomOfTopDivider); 11329cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.draw(canvas); 11339cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 11349cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the bottom divider 11359cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int topOfBottomDivider = topOfTopDivider + mSelectorElementHeight; 11369cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int bottomOfBottomDivider = bottomOfTopDivider + mSelectorElementHeight; 11379cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setBounds(0, topOfBottomDivider, mRight, bottomOfBottomDivider); 11389cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.draw(canvas); 11399cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1141fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 11423fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov @Override 11433fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov public void sendAccessibilityEvent(int eventType) { 11443fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov // Do not send accessibility events - we want the user to 11453fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov // perceive this widget as several controls rather as a whole. 11463fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov } 11473fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov 114868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1149a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov * Resets the selector indices and clear the cached 1150a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov * string representation of these indices. 1151a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov */ 1152e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private void resetSelectorWheelIndices() { 1153a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov mSelectorIndexToStringCache.clear(); 1154a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov int[] selectorIdices = getSelectorIndices(); 1155a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov for (int i = 0; i < selectorIdices.length; i++) { 1156a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov selectorIdices[i] = Integer.MIN_VALUE; 1157a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1158a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1159a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov 1160a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov /** 1161206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets the current value of this NumberPicker, and sets mPrevious to the 1162206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * previous value. If current is greater than mEnd less than mStart, the 1163206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * value of mCurrent is wrapped around. Subclasses can override this to 1164206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * change the wrapping behavior 116568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 116668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * @param current the new value of the NumberPicker 116768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1168206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void changeCurrent(int current) { 1169e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mValue == current) { 1170206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1171206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wrap around the values if we go past the start or end 1173e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1174206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov current = getWrappedSelectorIndex(current); 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1176e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int previous = mValue; 1177e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setValue(current); 1178206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov notifyChange(previous, current); 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1180fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 118168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1182206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets the <code>alpha</code> of the {@link Paint} for drawing the selector 1183206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * wheel. 118468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1185206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @SuppressWarnings("unused") 1186206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Called by ShowInputControlsAnimator via reflection 1187206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setSelectorPaintAlpha(int alpha) { 1188206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint.setAlpha(alpha); 1189206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDrawSelectorWheel) { 1190206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 119468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 119558f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov * @return If the <code>event</code> is in the <code>view</code>. 119668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 119758f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov private boolean isEventInViewHitRect(MotionEvent event, View view) { 119858f51255eb20f9c4d16c11554f372ff92d45fcc7Svetoslav Ganov view.getHitRect(mTempRect); 1199206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mTempRect.contains((int) event.getX(), (int) event.getY()); 1200206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1201206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1202206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1203206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets if to <code>drawSelectionWheel</code>. 1204206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 12053fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov private void setDrawScrollWheel(boolean drawSelectorWheel) { 1206206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDrawSelectorWheel = drawSelectorWheel; 1207206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // do not fade if the selector wheel not shown 1208206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setVerticalFadingEdgeEnabled(drawSelectorWheel); 12093fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov 12103fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov if (mFlingable && mDrawSelectorWheel 12113fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov && AccessibilityManager.getInstance(mContext).isEnabled()) { 12123fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov AccessibilityManager.getInstance(mContext).interrupt(); 12133fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov String text = mContext.getString(R.string.number_picker_increment_scroll_action); 12143fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov mInputText.setContentDescription(text); 12153fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov mInputText.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 12163fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov mInputText.setContentDescription(null); 12173fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov } 1218206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1219206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 12209cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void initializeScrollWheel() { 12219cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mInitialScrollOffset != Integer.MIN_VALUE) { 12229cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov return; 12239cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12249cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 12259cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int totalTextHeight = selectorIndices.length * mTextSize; 122601fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov float totalTextGapHeight = (mBottom - mTop) - totalTextHeight; 122701fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov float textGapCount = selectorIndices.length - 1; 122801fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov int selectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f); 12299cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectorElementHeight = mTextSize + selectorTextGapHeight; 1230eeafd4296b7cf4c2ad9c985562f6d70e2a3ffc03Chet Haase // Ensure that the middle item is positioned the same as the text in mInputText 1231eeafd4296b7cf4c2ad9c985562f6d70e2a3ffc03Chet Haase int editTextTextPosition = mInputText.getBaseline() + mInputText.getTop(); 1232eeafd4296b7cf4c2ad9c985562f6d70e2a3ffc03Chet Haase mInitialScrollOffset = editTextTextPosition - 1233eeafd4296b7cf4c2ad9c985562f6d70e2a3ffc03Chet Haase (mSelectorElementHeight * SELECTOR_MIDDLE_ITEM_INDEX); 12346a19fcde07527706c2a9175e0b9f2a71549b7ffeSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 12359cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov updateInputTextView(); 12369cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12379cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 1238206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1239206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Callback invoked upon completion of a given <code>scroller</code>. 1240206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1241206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void onScrollerFinished(Scroller scroller) { 1242206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller == mFlingScroller) { 1243206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(0); 12449cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1246206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 12479cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1250fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1251206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 12529cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * Handles transition to a given <code>scrollState</code> 125350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 12549cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void onScrollStateChange(int scrollState) { 12559cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mScrollState == scrollState) { 12569cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov return; 12579cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 12589cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mScrollState = scrollState; 12599cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mOnScrollListener != null) { 12604bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mOnScrollListener.onScrollStateChange(this, scrollState); 126150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 126250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 126350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 126450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 1265206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flings the selector with the given <code>velocityY</code>. 1266206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1267206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void fling(int velocityY) { 1268206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 1269206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller flingScroller = mFlingScroller; 1270206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1271e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1272206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (velocityY > 0) { 1273206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1274206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1275206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1276206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1277206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1278206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (velocityY > 0) { 1279e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int maxY = mTextSize * (mValue - mMinValue); 1280206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, maxY); 1281206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1282e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int startY = mTextSize * (mMaxValue - mValue); 1283206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int maxY = startY; 1284206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, startY, 0, velocityY, 0, 0, 0, maxY); 12852bf761c20253222a763bce9a63d14c48ab08a556Suchi Amalapurapu } 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1287206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1288206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1291206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1292206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Hides the input controls which is the up/down arrows and the text field. 1293206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1294206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void hideInputControls() { 1295206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.cancel(); 1296206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(INVISIBLE); 1297206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(INVISIBLE); 1298206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setVisibility(INVISIBLE); 1299206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1300c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1301206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1302206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Show the input controls by making them visible and animating the alpha 1303206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * property up/down arrows. 13049cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * 13059cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * @param animationDuration The duration of the animation. 1306206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 13079cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void showInputControls(long animationDuration) { 1308206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 1309206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setVisibility(VISIBLE); 13109cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mShowInputControlsAnimator.setDuration(animationDuration); 1311206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.start(); 1312206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1313c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1314206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1315206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the visibility state of the increment and decrement buttons. 1316206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1317206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void updateIncrementAndDecrementButtonsVisibilityState() { 1318e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel || mValue < mMaxValue) { 1319206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(VISIBLE); 1320206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1321206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(INVISIBLE); 1322206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1323e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel || mValue > mMinValue) { 1324206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(VISIBLE); 1325206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1326206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(INVISIBLE); 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1331206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selector indices array with proper values with the current as 1332206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * the middle one. 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1334206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int[] getSelectorIndices() { 1335e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int current = getValue(); 1336206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] != current) { 1337206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < mSelectorIndices.length; i++) { 1338206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX); 1339e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1340206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndex = getWrappedSelectorIndex(selectorIndex); 1341206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1342206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorIndices[i] = selectorIndex; 1343206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(mSelectorIndices[i]); 1344206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1345206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1346206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mSelectorIndices; 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1348fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 134968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1350206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The wrapped index <code>selectorIndex</code> value. 135168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1352206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getWrappedSelectorIndex(int selectorIndex) { 1353e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndex > mMaxValue) { 1354e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1; 1355e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } else if (selectorIndex < mMinValue) { 1356e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1; 1357206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1358206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return selectorIndex; 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1360fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1361206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1362206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Increments the <code>selectorIndices</code> whose string representations 1363206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1364206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1365206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void incrementScrollSelectorIndices(int[] selectorIndices) { 1366206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length - 1; i++) { 1367206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i + 1]; 1368206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1369206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[selectorIndices.length - 2] + 1; 1370e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel && nextScrollSelectorIndex > mMaxValue) { 1371e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov nextScrollSelectorIndex = mMinValue; 1372206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1373206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[selectorIndices.length - 1] = nextScrollSelectorIndex; 1374206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1375206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1376fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1377206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1378206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Decrements the <code>selectorIndices</code> whose string representations 1379206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1380206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1381206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void decrementSelectorIndices(int[] selectorIndices) { 1382206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = selectorIndices.length - 1; i > 0; i--) { 1383206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i - 1]; 1384206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1385206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[1] - 1; 1386e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel && nextScrollSelectorIndex < mMinValue) { 1387e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov nextScrollSelectorIndex = mMaxValue; 1388206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1389206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[0] = nextScrollSelectorIndex; 1390206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1391206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1392fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1393206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1394206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensures we have a cached string representation of the given <code> 1395206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * selectorIndex</code> 1396206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * to avoid multiple instantiations of the same string. 1397206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1398206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void ensureCachedScrollSelectorValue(int selectorIndex) { 1399206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov SparseArray<String> cache = mSelectorIndexToStringCache; 1400206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = cache.get(selectorIndex); 1401206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scrollSelectorValue != null) { 1402206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1403206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1404e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndex < mMinValue || selectorIndex > mMaxValue) { 1405206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = ""; 1406206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1407206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues != null) { 1408e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int displayedValueIndex = selectorIndex - mMinValue; 140950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov scrollSelectorValue = mDisplayedValues[displayedValueIndex]; 1410206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1411206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = formatNumber(selectorIndex); 14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1414206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov cache.put(selectorIndex, scrollSelectorValue); 14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1416fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1417206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private String formatNumber(int value) { 1418e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return (mFormatter != null) ? mFormatter.format(value) : String.valueOf(value); 1419206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1421206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void validateInputTextView(View v) { 1422206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(((TextView) v).getText()); 1423206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(str)) { 1424206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Restore to the old value as we don't allow empty values 1425206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 1426206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1427206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Check the new value and ensure it's in range 1428206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int current = getSelectedPos(str.toString()); 1429206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(current); 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1431206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1432fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1433206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1434206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the view of this NumberPicker. If displayValues were specified in 14359cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * the string corresponding to the index specified by the current value will 14369cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * be returned. Otherwise, the formatter specified in {@link #setFormatter} 14379cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * will be used to format the number. 1438206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1439206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void updateInputTextView() { 1440206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1441206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * If we don't have displayed values then use the current number else 1442206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * find the correct value in the displayed values for the current 1443206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * number. 1444206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1445206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 1446e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setText(formatNumber(mValue)); 1447206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1448e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setText(mDisplayedValues[mValue - mMinValue]); 14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1450206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mInputText.getText().length()); 14513fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov 14523fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov if (mFlingable && AccessibilityManager.getInstance(mContext).isEnabled()) { 14533fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov String text = mContext.getString(R.string.number_picker_increment_scroll_mode, 14543fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov mInputText.getText()); 14553fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov mInputText.setContentDescription(text); 14563fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov } 1457206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1458fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1459206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1460206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Notifies the listener, if registered, of a change of the value of this 1461206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * NumberPicker. 1462206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1463206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void notifyChange(int previous, int current) { 1464cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov if (mOnValueChangeListener != null) { 1465cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mOnValueChangeListener.onValueChange(this, previous, mValue); 1466206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1467206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1470206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts a command for updating the current value every <code>updateMillis 1471206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * </code>. 1472206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1473206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postUpdateValueFromLongPress(int updateMillis) { 1474206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 1475206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 1476206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mUpdateFromLongPressCommand == null) { 1477206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateFromLongPressCommand = new UpdateValueFromLongPressCommand(); 1478206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1479206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateFromLongPressCommand.setUpdateStep(updateMillis); 1480206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mUpdateFromLongPressCommand); 1481206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1483206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1484206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Removes all pending callback from the message queue. 1485206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1486206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void removeAllCallbacks() { 1487206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mUpdateFromLongPressCommand != null) { 1488206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mUpdateFromLongPressCommand); 1489206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1490206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerCommand != null) { 1491206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mAdjustScrollerCommand); 1492206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1493206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand != null) { 1494206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1498206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1499206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selected index given its displayed <code>value</code>. 1500206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1501206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getSelectedPos(String value) { 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisplayedValues == null) { 1503aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy try { 1504206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 1505aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } catch (NumberFormatException e) { 1506206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 1507aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mDisplayedValues.length; i++) { 1510206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Don't force the user to type in jan when ja will do 1511206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov value = value.toLowerCase(); 1512206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues[i].toLowerCase().startsWith(value)) { 1513e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue + i; 15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1516fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1517206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1518206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The user might have typed in a number into the month field i.e. 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10 instead of OCT so support that too. 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1522206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 1524fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1525206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1528e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue; 15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1532206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link SetSelectionCommand} from the given <code>selectionStart 1533206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * </code> to 1534206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * <code>selectionEnd</code>. 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1536206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postSetSelectionCommand(int selectionStart, int selectionEnd) { 1537206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand == null) { 1538206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand = new SetSelectionCommand(); 1539206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1540206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 1541206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1542206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionStart = selectionStart; 1543206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionEnd = selectionEnd; 1544206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mSetSelectionCommand); 15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 154668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 154768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1548206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link AdjustScrollerCommand} within the given <code> 1549206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * delayMillis</code> 1550206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * . 155168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1552206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postAdjustScrollerCommand(int delayMillis) { 1553206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerCommand == null) { 1554206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerCommand = new AdjustScrollerCommand(); 1555206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1556206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mAdjustScrollerCommand); 1557206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1558206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postDelayed(mAdjustScrollerCommand, delayMillis); 155968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 156068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 156168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1562206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Filter for accepting only valid indices or prefixes of the string 1563206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * representation of valid indices. 156468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1565206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class InputTextFilter extends NumberKeyListener { 1566206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1567206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // XXX This doesn't allow for range limits when controlled by a 1568206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // soft input method! 1569206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public int getInputType() { 1570206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return InputType.TYPE_CLASS_TEXT; 1571206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1572206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1573206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1574206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected char[] getAcceptedChars() { 1575206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return DIGIT_CHARACTERS; 1576206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1577206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1578206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1579206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public CharSequence filter(CharSequence source, int start, int end, Spanned dest, 1580206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int dstart, int dend) { 1581206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 1582206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = super.filter(source, start, end, dest, dstart, dend); 1583206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (filtered == null) { 1584206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov filtered = source.subSequence(start, end); 1585206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1586206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1587206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 1588206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 1589206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1590206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ("".equals(result)) { 1591206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return result; 1592206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1593206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int val = getSelectedPos(result); 1594206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1595206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1596206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensure the user can't type in a value greater than the max 1597206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * allowed. We have to allow less than min as the user might 1598206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * want to delete some numbers and then type a new number. 1599206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1600e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (val > mMaxValue) { 1601206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1602206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1603206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return filtered; 1604206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1605206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1606206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = String.valueOf(source.subSequence(start, end)); 1607206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(filtered)) { 1608206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1609206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1610206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 1611206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 1612206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(result).toLowerCase(); 1613206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (String val : mDisplayedValues) { 1614206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String valLowerCase = val.toLowerCase(); 1615206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (valLowerCase.startsWith(str)) { 1616206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postSetSelectionCommand(result.length(), val.length()); 1617206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return val.subSequence(dstart, val.length()); 1618206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1619206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1620206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1621206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1622206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1623206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1624206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1625206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1626206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for setting the input text selection. 1627206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1628206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class SetSelectionCommand implements Runnable { 1629206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionStart; 1630206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1631206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionEnd; 1632206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1633206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1634206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mSelectionStart, mSelectionEnd); 1635206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1636206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1637206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1638206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1639206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for adjusting the scroller to show in its center the closest of 1640206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * the displayed items. 1641206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1642206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class AdjustScrollerCommand implements Runnable { 1643206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1644206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 164534c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (mInitialScrollOffset == mCurrentScrollOffset) { 164634c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov updateInputTextView(); 16479cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov showInputControls(mShowInputControlsAnimimationDuration); 164834c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov return; 164934c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov } 165034c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov // adjust to the closest value 1651206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaY = mInitialScrollOffset - mCurrentScrollOffset; 165234c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (Math.abs(deltaY) > mSelectorElementHeight / 2) { 165334c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov deltaY += (deltaY > 0) ? -mSelectorElementHeight : mSelectorElementHeight; 165434c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov } 16559cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mAdjustScroller.startScroll(0, 0, 0, deltaY, SELECTOR_ADJUSTMENT_DURATION_MILLIS); 1656206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 1657206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1658206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1659206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1660206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1661206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for updating the current value from a long press. 1662206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1663206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class UpdateValueFromLongPressCommand implements Runnable { 1664206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mUpdateStep = 0; 1665206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1666206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setUpdateStep(int updateStep) { 1667206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateStep = updateStep; 1668206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1669206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1670206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1671e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov changeCurrent(mValue + mUpdateStep); 16724bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov postDelayed(this, mLongPressUpdateInterval); 1673206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 167468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 16757762d93621f508f4410fd37b5bbdfec0071b0420Paul Westbrook} 1676