NumberPicker.java revision bf80562d22b2bbe7944d80d0524c69d0238010cb
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; 33206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.graphics.Paint.Align; 3450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganovimport android.graphics.Rect; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputFilter; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputType; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Spanned; 38206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.text.TextUtils; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.method.NumberKeyListener; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 41206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.util.SparseArray; 42206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.KeyEvent; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 4450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganovimport android.view.LayoutInflater.Filter; 45206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.MotionEvent; 46206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.VelocityTracker; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 48206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.ViewConfiguration; 49206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.animation.OvershootInterpolator; 50206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.inputmethod.InputMethodManager; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook/** 534bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * A widget that enables the user to select a number form a predefined range. 544bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * The widget presents an input filed and up and down buttons for selecting the 554bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * current value. Pressing/long pressing the up and down buttons increments and 564bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * decrements the current value respectively. Touching the input filed shows a 574bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * scroll wheel, tapping on which while shown and not moving allows direct edit 584bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * of the current value. Sliding motions up or down hide the buttons and the 594bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * input filed, show the scroll wheel, and rotate the latter. Flinging is 604bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * also supported. The widget enables mapping from positions to strings such 614bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * that instead the position index the corresponding string is displayed. 624bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 634bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * For an example of using this widget, see {@link android.widget.TimePicker}. 644bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 6568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 6668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook@Widget 6768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrookpublic class NumberPicker extends LinearLayout { 68fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 6968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 70206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The index of the middle selector item. 7168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 72206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_MIDDLE_ITEM_INDEX = 2; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 75206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The coefficient by which to adjust (divide) the max fling velocity. 7668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 77206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT = 8; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 80206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The the duration for adjusting the selector wheel. 81206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 82206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_ADJUSTMENT_DURATION_MILLIS = 800; 83fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 84206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 85206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The the delay for showing the input controls after a single tap on the 86206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * input text. 87206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 88206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SHOW_INPUT_CONTROLS_DELAY_MILLIS = ViewConfiguration 89206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov .getDoubleTapTimeout(); 90206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 91206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 92206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The update step for incrementing the current value. 93206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 94206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int UPDATE_STEP_INCREMENT = 1; 95206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 96206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 97206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The update step for decrementing the current value. 98206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 99206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int UPDATE_STEP_DECREMENT = -1; 100206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 101206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 102206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The strength of fading in the top and bottom while drawing the selector. 103206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 104206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final float TOP_AND_BOTTOM_FADING_EDGE_STRENGTH = 0.9f; 105206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 106206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 107206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The numbers accepted by the input text's {@link Filter} 108206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 109206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final char[] DIGIT_CHARACTERS = new char[] { 110206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 111206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 112206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 113206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 114206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Use a custom NumberPicker formatting callback to use two-digit minutes 115206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * strings like "01". Keeping a static formatter etc. is the most efficient 116206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * way to do this; it avoids creating temporary objects on every call to 117206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * format(). 118206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 119206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() { 120206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final StringBuilder mBuilder = new StringBuilder(); 121206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 122f0ef665299d795df7905897e1c337e37891dafefJean-Baptiste Queru final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US); 123206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 124206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final Object[] mArgs = new Object[1]; 125206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 126206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public String toString(int value) { 127206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mArgs[0] = value; 128206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBuilder.delete(0, mBuilder.length()); 129206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mFmt.format("%02d", mArgs); 130206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mFmt.toString(); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 134206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 135206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The increment button. 136206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 137206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final ImageButton mIncrementButton; 138206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 139206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 140206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The decrement button. 141206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 142206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final ImageButton mDecrementButton; 143206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 144206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 145206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The text for showing the current value. 146206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 147206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final EditText mInputText; 148206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 149206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 150206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The height of the text. 151206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 152206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int mTextSize; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 154206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 155206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The values to be displayed instead the indices. 156206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] mDisplayedValues; 15868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 15968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 16068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Lower value of the range of numbers allowed for the NumberPicker 16168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 16268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook private int mStart; 16368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 16468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 16568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Upper value of the range of numbers allowed for the NumberPicker 16668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 16768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook private int mEnd; 16868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 16968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 17068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Current value of this NumberPicker 17168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 17268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook private int mCurrent; 17368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 17468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 175206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Listener to be notified upon current value change. 17668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1774bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov private OnChangeListener mOnChangeListener; 17850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 17950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 18050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * Listener to be notified upon scroll state change. 18150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 18250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov private OnScrollListener mOnScrollListener; 183206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 184206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 185206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Formatter for for displaying the current value. 186206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Formatter mFormatter; 188fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 189206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 190206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The speed for updating the value form long press. 191206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1924bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov private long mLongPressUpdateInterval = 300; 193fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 19468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 195206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Cache for the string representation of selector indices. 196206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 197206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final SparseArray<String> mSelectorIndexToStringCache = new SparseArray<String>(); 198206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 199206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 200206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The selector indices whose value are show by the selector. 201206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 202206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int[] mSelectorIndices = new int[] { 203206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, 204206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Integer.MIN_VALUE 205206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 206206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 207206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 208206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Paint} for drawing the selector. 209206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 210206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Paint mSelectorPaint; 211206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 212206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 213206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The height of a selector element (text + gap). 214206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 215206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectorElementHeight; 216206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 217206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 218206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The initial offset of the scroll selector. 219206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 220206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mInitialScrollOffset = Integer.MIN_VALUE; 221206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 222206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 223206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The current offset of the scroll selector. 224206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 225206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mCurrentScrollOffset; 226206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 227206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 228206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Scroller} responsible for flinging the selector. 229206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 230206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Scroller mFlingScroller; 231206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 232206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 233206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Scroller} responsible for adjusting the selector. 234206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 235206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Scroller mAdjustScroller; 236206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 237206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 238206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The previous Y coordinate while scrolling the selector. 239206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 240206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mPreviousScrollerY; 241206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 242206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 243206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for setting the input text selection. 244206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 245206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private SetSelectionCommand mSetSelectionCommand; 246206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 247206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 248206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for adjusting the scroller. 249206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 250206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private AdjustScrollerCommand mAdjustScrollerCommand; 251206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 252206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 253206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for updating the current value from long 254206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * press. 255206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 256206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private UpdateValueFromLongPressCommand mUpdateFromLongPressCommand; 257206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 258206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 259206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * {@link Animator} for showing the up/down arrows. 260206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 261206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final AnimatorSet mShowInputControlsAnimator; 262206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 263206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 264206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The Y position of the last down event. 265206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 266206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private float mLastDownEventY; 267206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 268206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 269206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The Y position of the last motion event. 270206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 271206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private float mLastMotionEventY; 272206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 273206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 274206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to begin edit on next up event. 275206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 276206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mBeginEditOnUpEvent; 277206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 278206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 279206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to adjust the selector wheel on next up event. 280206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 281206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mAdjustScrollerOnUpEvent; 282206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 283206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 284206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag if to draw the selector wheel. 285206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 286206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mDrawSelectorWheel; 287206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 288206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 289206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Determines speed during touch scrolling. 290206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 291206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private VelocityTracker mVelocityTracker; 292206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 293206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 294206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledTouchSlop() 295206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 296206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mTouchSlop; 297206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 298206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 299206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledMinimumFlingVelocity() 300206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 301206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mMinimumFlingVelocity; 302206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 303206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 304206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledMaximumFlingVelocity() 305206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 306206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mMaximumFlingVelocity; 307206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 308206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 309206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag whether the selector should wrap around. 310206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 311206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mWrapSelector; 312206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 313206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 314206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The back ground color used to optimize scroller fading. 31568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 316206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int mSolidColor; 317206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 318206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 319206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Reusable {@link Rect} instance. 320206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 321206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Rect mTempRect = new Rect(); 322206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 323206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 32450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The current scroll state of the number picker. 32550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 32650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE; 32750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 32850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 329206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The callback interface used to indicate the number value has changed. 330206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 3314bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public interface OnChangeListener { 332206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 3334bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Called upon a change of the current value. 3344bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 335206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param picker The NumberPicker associated with this listener. 336206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param oldVal The previous value. 337206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param newVal The new value. 338206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 3394bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov void onChange(NumberPicker picker, int oldVal, int newVal); 340206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 341206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 342206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 34350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * Interface for listening to the picker scroll state. 34450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 34550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public interface OnScrollListener { 34650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 34750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 34850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The view is not scrolling. 34950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 35050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_IDLE = 0; 35150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 35250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 35350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The user is scrolling using touch, and their finger is still on the screen. 35450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 35550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_TOUCH_SCROLL = 1; 35650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 35750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 35850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The user had previously been scrolling using touch and performed a fling. 35950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 36050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_FLING = 2; 36150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 36250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 36350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * Callback method to be invoked while the number picker is being scrolled. 36450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 36550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * @param view The view whose scroll state is being reported 36650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE}, 36750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}. 36850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 3694bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void onScrollStateChange(NumberPicker view, int scrollState); 37050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 37150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 37250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 3734bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Interface used to format the number into a string for presentation. 374206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 375206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public interface Formatter { 3764bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 3774bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 3784bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Formats a string representation of the current index. 3794bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 3804bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param value The currently selected value. 3814bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @return A formatted string representation. 3824bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 3834bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public String toString(int value); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 385fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 38668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 3874bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Create a new number picker. 3884bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 3894bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param context The application environment. 3904bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 3914bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public NumberPicker(Context context) { 3924bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov this(context, null); 3934bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 3944bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 3954bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 3964bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Create a new number picker. 397206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 398206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param context The application environment. 399206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param attrs A collection of attributes. 40068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public NumberPicker(Context context, AttributeSet attrs) { 402206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov this(context, attrs, R.attr.numberPickerStyle); 403206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 404206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 405206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 406206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Create a new number picker 407206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 408206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param context the application environment. 409206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param attrs a collection of attributes. 410206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param defStyle The default style to apply to this view. 411206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 412206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public NumberPicker(Context context, AttributeSet attrs, int defStyle) { 413206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov super(context, attrs, defStyle); 414206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 415206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // process style attributes 416206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov TypedArray attributesArray = context.obtainStyledAttributes(attrs, 417206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov R.styleable.NumberPicker, defStyle, 0); 418206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int orientation = attributesArray.getInt(R.styleable.NumberPicker_orientation, VERTICAL); 419206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setOrientation(orientation); 420206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSolidColor = attributesArray.getColor(R.styleable.NumberPicker_solidColor, 0); 421206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov attributesArray.recycle(); 422206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 423206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // By default Linearlayout that we extend is not drawn. This is 424206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // its draw() method is not called but dispatchDraw() is called 425206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // directly (see ViewGroup.drawChild()). However, this class uses 426206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // the fading edge effect implemented by View and we need our 427206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // draw() method to be called. Therefore, we declare we will draw. 428206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setWillNotDraw(false); 429206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(false); 430206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 431206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( 432206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Context.LAYOUT_INFLATER_SERVICE); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inflater.inflate(R.layout.number_picker, this, true); 43468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 435206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov OnClickListener onClickListener = new OnClickListener() { 43668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook public void onClick(View v) { 437206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 438206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (v.getId() == R.id.increment) { 43968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook changeCurrent(mCurrent + 1); 440206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 44168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook changeCurrent(mCurrent - 1); 44268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 44368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 44468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook }; 44568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 446206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov OnLongClickListener onLongClickListener = new OnLongClickListener() { 447206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onLongClick(View v) { 448206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 449206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (v.getId() == R.id.increment) { 450206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postUpdateValueFromLongPress(UPDATE_STEP_INCREMENT); 451206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 452206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postUpdateValueFromLongPress(UPDATE_STEP_DECREMENT); 453206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 454206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 455206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 456206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 45768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 458206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // increment button 459206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton = (ImageButton) findViewById(R.id.increment); 460206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setOnClickListener(onClickListener); 461206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setOnLongClickListener(onLongClickListener); 462206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 463206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // decrement button 464206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton = (ImageButton) findViewById(R.id.decrement); 465206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setOnClickListener(onClickListener); 466206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setOnLongClickListener(onLongClickListener); 467206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 468206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // input text 469206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText = (EditText) findViewById(R.id.timepicker_input); 470206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setOnFocusChangeListener(new OnFocusChangeListener() { 471206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onFocusChange(View v, boolean hasFocus) { 47268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook if (!hasFocus) { 473206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov validateInputTextView(v); 47468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 47568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 476206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 477206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setFilters(new InputFilter[] { 478206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov new InputTextFilter() 479206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 48068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 481206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 482206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 483206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // initialize constants 484206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTouchSlop = ViewConfiguration.getTapTimeout(); 485206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ViewConfiguration configuration = ViewConfiguration.get(context); 486206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTouchSlop = configuration.getScaledTouchSlop(); 487206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); 488206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity() 489206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov / SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT; 490206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTextSize = (int) mInputText.getTextSize(); 491206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 492206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the selector wheel paint 493206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Paint paint = new Paint(); 494206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setAntiAlias(true); 495206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTextAlign(Align.CENTER); 496206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTextSize(mTextSize); 497206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTypeface(mInputText.getTypeface()); 498206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ColorStateList colors = mInputText.getTextColors(); 499206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int color = colors.getColorForState(ENABLED_STATE_SET, Color.WHITE); 500206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setColor(color); 501206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint = paint; 502206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 503206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the animator for showing the input controls 504206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ValueAnimator fadeScroller = ObjectAnimator.ofInt(this, "selectorPaintAlpha", 255, 0); 505206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ObjectAnimator showIncrementButton = ObjectAnimator.ofFloat(mIncrementButton, 506206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov "alpha", 0, 1); 507206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final ObjectAnimator showDecrementButton = ObjectAnimator.ofFloat(mDecrementButton, 508206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov "alpha", 0, 1); 509206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator = new AnimatorSet(); 510206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.playTogether(fadeScroller, showIncrementButton, 511206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov showDecrementButton); 512206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.setDuration(getResources().getInteger( 513206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov R.integer.config_longAnimTime)); 514206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.addListener(new AnimatorListenerAdapter() { 515206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean mCanceled = false; 516206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 517206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 518206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onAnimationEnd(Animator animation) { 519206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mCanceled) { 520206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // if canceled => we still want the wheel drawn 521206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(false); 52268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 523206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCanceled = false; 524206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint.setAlpha(255); 525206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 52668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 52768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 528206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 529206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onAnimationCancel(Animator animation) { 530206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mShowInputControlsAnimator.isRunning()) { 531206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCanceled = true; 532206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 533206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 534206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 53568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 536206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the fling and adjust scrollers 537bf80562d22b2bbe7944d80d0524c69d0238010cbSvetoslav Ganov mFlingScroller = new Scroller(getContext(), null, true); 538206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScroller = new Scroller(getContext(), new OvershootInterpolator()); 539fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 540206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 541206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 542206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 543206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 544206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 545206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onWindowFocusChanged(boolean hasWindowFocus) { 546206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov super.onWindowFocusChanged(hasWindowFocus); 547206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!hasWindowFocus) { 548206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 549206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 550206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 551206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 552206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 553206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onInterceptTouchEvent(MotionEvent event) { 554206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (event.getActionMasked()) { 555206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_DOWN: 556206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mLastMotionEventY = mLastDownEventY = event.getY(); 557206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 558206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 559206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = true; 560206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDrawSelectorWheel) { 56150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov boolean scrollersFinished = mFlingScroller.isFinished() 562206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov && mAdjustScroller.isFinished(); 56350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (!scrollersFinished) { 56450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mFlingScroller.forceFinished(true); 56550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mAdjustScroller.forceFinished(true); 56650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_IDLE); 56750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 56850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mBeginEditOnUpEvent = scrollersFinished; 569206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = true; 570206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov hideInputControls(); 571206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 572206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 573206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (isEventInInputText(event)) { 574206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerOnUpEvent = false; 575206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(true); 576206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov hideInputControls(); 577206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 578206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 579206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 580206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_MOVE: 581206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float currentMoveY = event.getY(); 582206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 583206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 584206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 58550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 586206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(true); 587206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov hideInputControls(); 588206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 589206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 590206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 591206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 592206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return false; 593206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 594206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 595206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 596206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onTouchEvent(MotionEvent ev) { 597206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mVelocityTracker == null) { 598206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = VelocityTracker.obtain(); 599206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 600206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.addMovement(ev); 601206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = ev.getActionMasked(); 602206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (action) { 603206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_MOVE: 604206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float currentMoveY = ev.getY(); 60550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (mBeginEditOnUpEvent 60650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov || mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 607206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 608206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 609206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBeginEditOnUpEvent = false; 61050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 611206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 612206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 613206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaMoveY = (int) (currentMoveY - mLastMotionEventY); 614206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, deltaMoveY); 615206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 616206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mLastMotionEventY = currentMoveY; 617206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 618206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov case MotionEvent.ACTION_UP: 619206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mBeginEditOnUpEvent) { 620206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setDrawSelectorWheel(false); 621206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov showInputControls(); 622206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.requestFocus(); 623206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov InputMethodManager imm = (InputMethodManager) getContext().getSystemService( 624206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Context.INPUT_METHOD_SERVICE); 625206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov imm.showSoftInput(mInputText, 0); 62650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mInputText.setSelection(0, mInputText.getText().length()); 627206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 628206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 629206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov VelocityTracker velocityTracker = mVelocityTracker; 630206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); 631206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int initialVelocity = (int) velocityTracker.getYVelocity(); 632206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (Math.abs(initialVelocity) > mMinimumFlingVelocity) { 633206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov fling(initialVelocity); 63450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_FLING); 635206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 636206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerOnUpEvent) { 637206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mFlingScroller.isFinished() && mAdjustScroller.isFinished()) { 638206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(0); 639206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 640206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 641206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(SHOW_INPUT_CONTROLS_DELAY_MILLIS); 642206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 643206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 644206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.recycle(); 645206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = null; 646206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov break; 647206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 648206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 649206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 650206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 651206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 652206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTouchEvent(MotionEvent event) { 653206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = event.getActionMasked(); 654206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ((action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) 655206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov && !isEventInInputText(event)) { 656206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 657206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 658206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTouchEvent(event); 659206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 660206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 661206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 662206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchKeyEvent(KeyEvent event) { 663206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int keyCode = event.getKeyCode(); 664206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) { 665206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 666206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 667206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchKeyEvent(event); 668206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 669206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 670206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 671206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTrackballEvent(MotionEvent event) { 672206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int action = event.getActionMasked(); 673206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 674206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 675206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 676206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTrackballEvent(event); 677206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 680206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void computeScroll() { 681206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mDrawSelectorWheel) { 682206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 683206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 684206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller scroller = mFlingScroller; 685206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 686206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller = mAdjustScroller; 687206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 688206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 689206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 690206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 691206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller.computeScrollOffset(); 692206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int currentScrollerY = scroller.getCurrY(); 693206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mPreviousScrollerY == 0) { 694206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = scroller.getStartY(); 695206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 696206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, currentScrollerY - mPreviousScrollerY); 697206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = currentScrollerY; 698206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 699206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov onScrollerFinished(scroller); 700206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 701206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 704fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 70568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 70668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Set the enabled state of this view. The interpretation of the enabled 70768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * state varies by subclass. 70868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 70968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * @param enabled True if this view is enabled, false otherwise. 71068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setEnabled(boolean enabled) { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setEnabled(enabled); 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIncrementButton.setEnabled(enabled); 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDecrementButton.setEnabled(enabled); 716206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setEnabled(enabled); 717206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 718206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 719206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 720206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Scrolls the selector with the given <code>vertical offset</code>. 721206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 722206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 723206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void scrollBy(int x, int y) { 724206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 725206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mInitialScrollOffset == Integer.MIN_VALUE) { 726206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int totalTextHeight = selectorIndices.length * mTextSize; 727206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int totalTextGapHeight = (mBottom - mTop) - totalTextHeight; 728206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int textGapCount = selectorIndices.length - 1; 729206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorTextGapHeight = totalTextGapHeight / textGapCount; 730206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // compensate for integer division loss of the components used to 731206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // calculate the text gap 732206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int integerDivisionLoss = (mTextSize + mBottom - mTop) % textGapCount; 733206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInitialScrollOffset = mCurrentScrollOffset = mTextSize - integerDivisionLoss / 2; 734206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorElementHeight = mTextSize + selectorTextGapHeight; 735206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 736206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 737206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mWrapSelector && y > 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mStart) { 738206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 739206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 740206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 741206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mWrapSelector && y < 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mEnd) { 742206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 743206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 744206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 745206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += y; 746206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset > mSelectorElementHeight) { 747206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset -= mSelectorElementHeight; 748206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov decrementSelectorIndices(selectorIndices); 749206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); 750206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mStart) { 751206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 752206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 753206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 754206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset < -mSelectorElementHeight) { 755206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += mSelectorElementHeight; 756206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov incrementScrollSelectorIndices(selectorIndices); 757206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]); 758206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mEnd) { 759206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 760206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 761206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 763fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 7644bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov @Override 7654bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public int getSolidColor() { 7664bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov return mSolidColor; 7674bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 7684bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 76968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 7704bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the listener to be notified on change of the current value. 771206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 7724bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param onChangeListener The listener. 77368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 7744bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setOnChangeListener(OnChangeListener onChangeListener) { 7754bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mOnChangeListener = onChangeListener; 77650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 77750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 77850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 7794bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set listener to be notified for scroll state changes. 78050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 78150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * @param onScrollListener the callback, should not be null. 78250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 78350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public void setOnScrollListener(OnScrollListener onScrollListener) { 78450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mOnScrollListener = onScrollListener; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 786fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 78768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 7884bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set the formatter to be used for formatting the current value. 7894bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 7904bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Note: If you have provided alternative values for the selected positons 7914bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * this formatter is never invoked. 7924bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 793206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 794206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param formatter the formatter object. If formatter is null, 7954bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * String.valueOf() will be used. 7964bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 7974bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @see #setRange(int, int, String[]) 79868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFormatter(Formatter formatter) { 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFormatter = formatter; 8012b9484f453ef307880a93240bb050b39af72bee2Svetoslav Ganov resetSelectorIndices(); 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 803fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 805206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Set the range of numbers allowed for the number picker. The current value 806206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be automatically set to the start. 807fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor * 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param start the start of the range (inclusive) 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param end the end of the range (inclusive) 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRange(int start, int end) { 812206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setRange(start, end, null); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 814fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 816206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Set the range of numbers allowed for the number picker. The current value 817206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be automatically set to the start. Also provide a mapping for values 8184bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * used to display to the user instead of the numbers in the range. 819fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor * 8204bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param start The start of the range (inclusive). 8214bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param end The end of the range (inclusive). 8224bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param displayedValues The values displayed to the user. 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRange(int start, int end, String[] displayedValues) { 825206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov boolean wrapSelector = (end - start) >= mSelectorIndices.length; 826206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setRange(start, end, displayedValues, wrapSelector); 827206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 828206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 829206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 830206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Set the range of numbers allowed for the number picker. The current value 831206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be automatically set to the start. Also provide a mapping for values 832206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * used to display to the user. 8334bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 8344bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Note: The <code>wrapSelectorWheel</code> argument is ignored if the range 8354bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * (difference between <code>start</code> and <code>end</code>) us less than 8364bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * five since this is the number of values shown by the selector wheel. 8374bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 838206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 839206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param start the start of the range (inclusive) 840206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param end the end of the range (inclusive) 841206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param displayedValues the values displayed to the user. 8424bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param wrapSelectorWheel Whether to wrap the selector wheel. 8434bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 8444bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @see #setWrapSelectorWheel(boolean) 845206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 8464bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setRange(int start, int end, String[] displayedValues, boolean wrapSelectorWheel) { 847a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov if (start == mStart && end == mEnd) { 848a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov return; 849a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 850a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov 851206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (start < 0 || end < 0) { 852206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov throw new IllegalArgumentException("start and end must be > 0"); 853206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 854a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayedValues = displayedValues; 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStart = start; 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnd = end; 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrent = start; 859206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 8604bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 861206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 8628bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powell 8638bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powell if (displayedValues != null) { 8648bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powell // Allow text entry rather than strictly numeric entry. 865206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT 866206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); 867206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 868206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 8698bcbebd4178b2e9aca9ee3bd9e1e12c42e74c8dbAdam Powell } 870206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 871a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov resetSelectorIndices(); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 873fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 87468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 87568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Set the current value for the number picker. 87668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 87768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * @param current the current value the start of the range (inclusive) 8784bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 879206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @throws IllegalArgumentException when current is not within the range of 8804bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * of the number picker. 88168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCurrent(int current) { 883a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov if (mCurrent == current) { 884a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov return; 885a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 88668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook if (current < mStart || current > mEnd) { 887206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov throw new IllegalArgumentException("current should be >= start and <= end"); 88868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrent = current; 890206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 891206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 892206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 893206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 894206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 8954bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets whether the selector wheel shown during flinging/scrolling should wrap 8964bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * around the beginning and end values. By default if the range is more than 8974bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * five (the number of items shown on the selector wheel) the selector wheel 8984bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * wrapping is enabled. 899206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 900206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param wrapSelector Whether to wrap. 901206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 9024bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setWrapSelectorWheel(boolean wrapSelector) { 903206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (wrapSelector && (mEnd - mStart) < mSelectorIndices.length) { 904206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov throw new IllegalStateException("Range less than selector items count."); 905206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 906206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (wrapSelector != mWrapSelector) { 907206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // force the selector indices array to be reinitialized 908206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] = Integer.MAX_VALUE; 909206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mWrapSelector = wrapSelector; 910206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9144bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the speed at which the numbers be incremented and decremented when 9154bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * the up and down buttons are long pressed respectively. 91668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 9174bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param intervalMillis The speed (in milliseconds) at which the numbers 9184bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * will be incremented and decremented (default 300ms). 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9204bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setOnLongPressUpdateInterval(long intervalMillis) { 9214bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mLongPressUpdateInterval = intervalMillis; 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 923fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 924206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 9254bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Returns the current value of the NumberPicker. 926206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 927206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return the current value. 928206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 929206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public int getCurrent() { 930206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mCurrent; 931206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 932206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 9334bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 9344bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Returns the range lower value of the NumberPicker. 9354bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 9364bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @return The lower number of the range. 9374bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 9384bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public int getRangeStart() { 9394bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov return mStart; 9404bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 9414bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 9424bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 9434bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Returns the range end value of the NumberPicker. 9444bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 9454bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @return The upper number of the range. 9464bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 9474bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public int getRangeEnd() { 9484bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov return mEnd; 949206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 950206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 951206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 952206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getTopFadingEdgeStrength() { 953206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 954206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 955206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 956206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 957206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getBottomFadingEdgeStrength() { 958206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 959206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 960206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 961206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 962206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDetachedFromWindow() { 963206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 964206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 965206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 966206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 967206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void dispatchDraw(Canvas canvas) { 968206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // There is a good reason for doing this. See comments in draw(). 969206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 970206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 971206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 972206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void draw(Canvas canvas) { 973206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Dispatch draw to our children only if we are not currently running 974206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // the animation for simultaneously fading out the scroll wheel and 975206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // showing in the buttons. This class takes advantage of the View 976206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // implementation of fading edges effect to draw the selector wheel. 977206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // However, in View.draw(), the fading is applied after all the children 978206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // have been drawn and we do not want this fading to be applied to the 979206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // buttons which are currently showing in. Therefore, we draw our 980206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // children 981206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // after we have completed drawing ourselves. 982206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 983c75ec3324e9e3e6500148cc2978caab90ea962e4Chet Haase super.draw(canvas); 984206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 985206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Draw our children if we are not showing the selector wheel of fading 986206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // it out 987206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mShowInputControlsAnimator.isRunning() || !mDrawSelectorWheel) { 988206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov long drawTime = getDrawingTime(); 989206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0, count = getChildCount(); i < count; i++) { 990206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov View child = getChildAt(i); 991206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!child.isShown()) { 992206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov continue; 993206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 994206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov drawChild(canvas, getChildAt(i), drawTime); 995206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 996206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 997206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 998206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 999206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1000206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDraw(Canvas canvas) { 1001206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // we only draw the selector wheel 1002206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (!mDrawSelectorWheel) { 1003206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1004206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1005206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float x = (mRight - mLeft) / 2; 1006206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float y = mCurrentScrollOffset; 1007206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1008206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int[] selectorIndices = getSelectorIndices(); 1009206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length; i++) { 1010206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = selectorIndices[i]; 1011206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex); 1012206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov canvas.drawText(scrollSelectorValue, x, y, mSelectorPaint); 1013206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov y += mSelectorElementHeight; 1014206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1016fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 101768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1018a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov * Resets the selector indices and clear the cached 1019a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov * string representation of these indices. 1020a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov */ 1021a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov private void resetSelectorIndices() { 1022a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov mSelectorIndexToStringCache.clear(); 1023a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov int[] selectorIdices = getSelectorIndices(); 1024a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov for (int i = 0; i < selectorIdices.length; i++) { 1025a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov selectorIdices[i] = Integer.MIN_VALUE; 1026a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1027a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1028a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov 1029a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov /** 1030206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets the current value of this NumberPicker, and sets mPrevious to the 1031206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * previous value. If current is greater than mEnd less than mStart, the 1032206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * value of mCurrent is wrapped around. Subclasses can override this to 1033206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * change the wrapping behavior 103468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 103568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * @param current the new value of the NumberPicker 103668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1037206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void changeCurrent(int current) { 1038206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mCurrent == current) { 1039206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1040206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wrap around the values if we go past the start or end 1042206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mWrapSelector) { 1043206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov current = getWrappedSelectorIndex(current); 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1045206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int previous = mCurrent; 1046206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setCurrent(current); 1047206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov notifyChange(previous, current); 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 105068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1051206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets the <code>alpha</code> of the {@link Paint} for drawing the selector 1052206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * wheel. 105368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1054206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @SuppressWarnings("unused") 1055206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Called by ShowInputControlsAnimator via reflection 1056206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setSelectorPaintAlpha(int alpha) { 1057206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorPaint.setAlpha(alpha); 1058206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDrawSelectorWheel) { 1059206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 106368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1064206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return If the <code>event</code> is in the input text. 106568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1066206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private boolean isEventInInputText(MotionEvent event) { 1067206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.getHitRect(mTempRect); 1068206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mTempRect.contains((int) event.getX(), (int) event.getY()); 1069206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1070206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1071206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1072206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Sets if to <code>drawSelectionWheel</code>. 1073206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1074206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setDrawSelectorWheel(boolean drawSelectorWheel) { 1075206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDrawSelectorWheel = drawSelectorWheel; 1076206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // do not fade if the selector wheel not shown 1077206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov setVerticalFadingEdgeEnabled(drawSelectorWheel); 1078206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1079206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1080206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1081206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Callback invoked upon completion of a given <code>scroller</code>. 1082206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1083206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void onScrollerFinished(Scroller scroller) { 1084206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller == mFlingScroller) { 1085206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(0); 108650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov tryNotifyScrollListener(OnScrollListener.SCROLL_STATE_IDLE); 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1088206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov showInputControls(); 1089206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1092fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1093206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 109450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * Notifies the scroll listener for the given <code>scrollState</code> 109550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * if the scroll state differs from the current scroll state. 109650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 109750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov private void tryNotifyScrollListener(int scrollState) { 109850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov if (mOnScrollListener != null && mScrollState != scrollState) { 109950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mScrollState = scrollState; 11004bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mOnScrollListener.onScrollStateChange(this, scrollState); 110150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 110250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 110350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 110450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 1105206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flings the selector with the given <code>velocityY</code>. 1106206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1107206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void fling(int velocityY) { 1108206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 1109206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller flingScroller = mFlingScroller; 1110206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1111206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mWrapSelector) { 1112206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (velocityY > 0) { 1113206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1114206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1115206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1116206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1117206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1118206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (velocityY > 0) { 1119206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int maxY = mTextSize * (mCurrent - mStart); 1120206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, maxY); 1121206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1122206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int startY = mTextSize * (mEnd - mCurrent); 1123206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int maxY = startY; 1124206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov flingScroller.fling(0, startY, 0, velocityY, 0, 0, 0, maxY); 11252bf761c20253222a763bce9a63d14c48ab08a556Suchi Amalapurapu } 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1127206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1128206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postAdjustScrollerCommand(flingScroller.getDuration()); 1129206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1132206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1133206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Hides the input controls which is the up/down arrows and the text field. 1134206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1135206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void hideInputControls() { 1136206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.cancel(); 1137206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(INVISIBLE); 1138206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(INVISIBLE); 1139206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setVisibility(INVISIBLE); 1140206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1141c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1142206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1143206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Show the input controls by making them visible and animating the alpha 1144206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * property up/down arrows. 1145206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1146206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void showInputControls() { 1147206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateIncrementAndDecrementButtonsVisibilityState(); 1148206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setVisibility(VISIBLE); 1149206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mShowInputControlsAnimator.start(); 1150206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1151c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1152206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1153206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the visibility state of the increment and decrement buttons. 1154206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1155206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void updateIncrementAndDecrementButtonsVisibilityState() { 1156206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mWrapSelector || mCurrent < mEnd) { 1157206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(VISIBLE); 1158206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1159206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mIncrementButton.setVisibility(INVISIBLE); 1160206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1161206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mWrapSelector || mCurrent > mStart) { 1162206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(VISIBLE); 1163206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1164206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mDecrementButton.setVisibility(INVISIBLE); 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1169206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selector indices array with proper values with the current as 1170206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * the middle one. 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1172206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int[] getSelectorIndices() { 1173206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int current = getCurrent(); 1174206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] != current) { 1175206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < mSelectorIndices.length; i++) { 1176206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX); 1177206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mWrapSelector) { 1178206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndex = getWrappedSelectorIndex(selectorIndex); 1179206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1180206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSelectorIndices[i] = selectorIndex; 1181206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(mSelectorIndices[i]); 1182206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1183206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1184206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mSelectorIndices; 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1186fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 118768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1188206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The wrapped index <code>selectorIndex</code> value. 118968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1190206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getWrappedSelectorIndex(int selectorIndex) { 1191206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (selectorIndex > mEnd) { 119299b539f6326a5f0df123b34766becec023bf7a84Svetoslav Ganov return mStart + (selectorIndex - mEnd) % (mEnd - mStart); 1193206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else if (selectorIndex < mStart) { 119499b539f6326a5f0df123b34766becec023bf7a84Svetoslav Ganov return mEnd - (mStart - selectorIndex) % (mEnd - mStart); 1195206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1196206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return selectorIndex; 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1198fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1199206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1200206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Increments the <code>selectorIndices</code> whose string representations 1201206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1202206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1203206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void incrementScrollSelectorIndices(int[] selectorIndices) { 1204206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length - 1; i++) { 1205206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i + 1]; 1206206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1207206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[selectorIndices.length - 2] + 1; 1208206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mWrapSelector && nextScrollSelectorIndex > mEnd) { 1209206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov nextScrollSelectorIndex = mStart; 1210206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1211206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[selectorIndices.length - 1] = nextScrollSelectorIndex; 1212206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1213206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1214fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1215206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1216206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Decrements the <code>selectorIndices</code> whose string representations 1217206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1218206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1219206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void decrementSelectorIndices(int[] selectorIndices) { 1220206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = selectorIndices.length - 1; i > 0; i--) { 1221206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i - 1]; 1222206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1223206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[1] - 1; 1224206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mWrapSelector && nextScrollSelectorIndex < mStart) { 1225206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov nextScrollSelectorIndex = mEnd; 1226206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1227206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[0] = nextScrollSelectorIndex; 1228206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1229206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1230fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1231206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1232206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensures we have a cached string representation of the given <code> 1233206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * selectorIndex</code> 1234206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * to avoid multiple instantiations of the same string. 1235206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1236206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void ensureCachedScrollSelectorValue(int selectorIndex) { 1237206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov SparseArray<String> cache = mSelectorIndexToStringCache; 1238206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = cache.get(selectorIndex); 1239206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scrollSelectorValue != null) { 1240206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1241206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1242206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (selectorIndex < mStart || selectorIndex > mEnd) { 1243206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = ""; 1244206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1245206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues != null) { 124650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov int displayedValueIndex = selectorIndex - mStart; 124750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov scrollSelectorValue = mDisplayedValues[displayedValueIndex]; 1248206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1249206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = formatNumber(selectorIndex); 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1252206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov cache.put(selectorIndex, scrollSelectorValue); 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1254fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1255206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private String formatNumber(int value) { 1256206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return (mFormatter != null) ? mFormatter.toString(value) : String.valueOf(value); 1257206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void validateInputTextView(View v) { 1260206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(((TextView) v).getText()); 1261206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(str)) { 1262206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Restore to the old value as we don't allow empty values 1263206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 1264206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1265206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Check the new value and ensure it's in range 1266206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int current = getSelectedPos(str.toString()); 1267206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(current); 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1270fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1271206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1272206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the view of this NumberPicker. If displayValues were specified in 1273206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * {@link #setRange}, the string corresponding to the index specified by the 1274206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * current value will be returned. Otherwise, the formatter specified in 1275206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * {@link #setFormatter} will be used to format the number. 1276206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1277206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void updateInputTextView() { 1278206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1279206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * If we don't have displayed values then use the current number else 1280206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * find the correct value in the displayed values for the current 1281206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * number. 1282206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1283206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 1284206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setText(formatNumber(mCurrent)); 1285206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1286206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setText(mDisplayedValues[mCurrent - mStart]); 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1288206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mInputText.getText().length()); 1289206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1290fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1291206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1292206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Notifies the listener, if registered, of a change of the value of this 1293206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * NumberPicker. 1294206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1295206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void notifyChange(int previous, int current) { 12964bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov if (mOnChangeListener != null) { 12974bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mOnChangeListener.onChange(this, previous, mCurrent); 1298206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1299206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1301206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1302206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts a command for updating the current value every <code>updateMillis 1303206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * </code>. 1304206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1305206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postUpdateValueFromLongPress(int updateMillis) { 1306206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 1307206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 1308206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mUpdateFromLongPressCommand == null) { 1309206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateFromLongPressCommand = new UpdateValueFromLongPressCommand(); 1310206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1311206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateFromLongPressCommand.setUpdateStep(updateMillis); 1312206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mUpdateFromLongPressCommand); 1313206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1315206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1316206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Removes all pending callback from the message queue. 1317206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1318206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void removeAllCallbacks() { 1319206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mUpdateFromLongPressCommand != null) { 1320206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mUpdateFromLongPressCommand); 1321206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1322206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerCommand != null) { 1323206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mAdjustScrollerCommand); 1324206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1325206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand != null) { 1326206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1330206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1331206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selected index given its displayed <code>value</code>. 1332206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1333206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getSelectedPos(String value) { 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisplayedValues == null) { 1335aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy try { 1336206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 1337aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } catch (NumberFormatException e) { 1338206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 1339aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mDisplayedValues.length; i++) { 1342206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Don't force the user to type in jan when ja will do 1343206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov value = value.toLowerCase(); 1344206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues[i].toLowerCase().startsWith(value)) { 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mStart + i; 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1348fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1349206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1350206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The user might have typed in a number into the month field i.e. 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10 instead of OCT so support that too. 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1354206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 1356fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1357206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mStart; 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1364206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link SetSelectionCommand} from the given <code>selectionStart 1365206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * </code> to 1366206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * <code>selectionEnd</code>. 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1368206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postSetSelectionCommand(int selectionStart, int selectionEnd) { 1369206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand == null) { 1370206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand = new SetSelectionCommand(); 1371206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1372206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 1373206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1374206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionStart = selectionStart; 1375206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionEnd = selectionEnd; 1376206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mSetSelectionCommand); 13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 137868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 137968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1380206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link AdjustScrollerCommand} within the given <code> 1381206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * delayMillis</code> 1382206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * . 138368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1384206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postAdjustScrollerCommand(int delayMillis) { 1385206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mAdjustScrollerCommand == null) { 1386206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScrollerCommand = new AdjustScrollerCommand(); 1387206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1388206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mAdjustScrollerCommand); 1389206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1390206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postDelayed(mAdjustScrollerCommand, delayMillis); 139168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 139268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 139368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1394206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Filter for accepting only valid indices or prefixes of the string 1395206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * representation of valid indices. 139668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1397206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class InputTextFilter extends NumberKeyListener { 1398206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1399206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // XXX This doesn't allow for range limits when controlled by a 1400206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // soft input method! 1401206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public int getInputType() { 1402206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return InputType.TYPE_CLASS_TEXT; 1403206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1404206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1405206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1406206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected char[] getAcceptedChars() { 1407206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return DIGIT_CHARACTERS; 1408206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1409206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1410206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1411206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public CharSequence filter(CharSequence source, int start, int end, Spanned dest, 1412206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int dstart, int dend) { 1413206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 1414206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = super.filter(source, start, end, dest, dstart, dend); 1415206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (filtered == null) { 1416206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov filtered = source.subSequence(start, end); 1417206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1418206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1419206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 1420206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 1421206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1422206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ("".equals(result)) { 1423206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return result; 1424206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1425206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int val = getSelectedPos(result); 1426206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1427206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1428206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensure the user can't type in a value greater than the max 1429206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * allowed. We have to allow less than min as the user might 1430206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * want to delete some numbers and then type a new number. 1431206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1432206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (val > mEnd) { 1433206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1434206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1435206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return filtered; 1436206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1437206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1438206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = String.valueOf(source.subSequence(start, end)); 1439206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(filtered)) { 1440206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1441206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1442206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 1443206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 1444206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(result).toLowerCase(); 1445206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (String val : mDisplayedValues) { 1446206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String valLowerCase = val.toLowerCase(); 1447206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (valLowerCase.startsWith(str)) { 1448206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postSetSelectionCommand(result.length(), val.length()); 1449206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return val.subSequence(dstart, val.length()); 1450206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1451206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1452206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 1453206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1454206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1455206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1456206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1457206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1458206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for setting the input text selection. 1459206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1460206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class SetSelectionCommand implements Runnable { 1461206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionStart; 1462206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1463206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionEnd; 1464206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1465206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1466206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mSelectionStart, mSelectionEnd); 1467206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1468206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1469206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1470206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1471206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for adjusting the scroller to show in its center the closest of 1472206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * the displayed items. 1473206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1474206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class AdjustScrollerCommand implements Runnable { 1475206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1476206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 1477206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaY = mInitialScrollOffset - mCurrentScrollOffset; 1478206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float delayCoef = (float) Math.abs(deltaY) / (float) mTextSize; 1479206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int duration = (int) (delayCoef * SELECTOR_ADJUSTMENT_DURATION_MILLIS); 1480206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mAdjustScroller.startScroll(0, 0, 0, deltaY, duration); 1481206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 1482206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1483206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1484206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1485206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1486206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for updating the current value from a long press. 1487206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1488206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class UpdateValueFromLongPressCommand implements Runnable { 1489206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mUpdateStep = 0; 1490206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1491206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void setUpdateStep(int updateStep) { 1492206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mUpdateStep = updateStep; 1493206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1494206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1495206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 1496206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov changeCurrent(mCurrent + mUpdateStep); 14974bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov postDelayed(this, mLongPressUpdateInterval); 1498206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 149968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 15007762d93621f508f4410fd37b5bbdfec0071b0420Paul Westbrook} 1501