NumberPicker.java revision 9eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2
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 19d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbyeimport android.annotation.IntDef; 2068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrookimport android.annotation.Widget; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 22206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.content.res.ColorStateList; 23206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.content.res.TypedArray; 24206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.graphics.Canvas; 25206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.graphics.Color; 26206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.graphics.Paint; 27e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganovimport android.graphics.Paint.Align; 28b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganovimport android.graphics.Rect; 299cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganovimport android.graphics.drawable.Drawable; 30aa780c110922148a6a4ba06734bb2b0bb8c98f93Svetoslav Ganovimport android.os.Bundle; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputFilter; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.InputType; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Spanned; 34206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.text.TextUtils; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.method.NumberKeyListener; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 37206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.util.SparseArray; 389cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganovimport android.util.TypedValue; 39206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.KeyEvent; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.LayoutInflater; 41b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganovimport android.view.LayoutInflater.Filter; 42206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.MotionEvent; 43206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.VelocityTracker; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 45206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.ViewConfiguration; 463fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 473fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganovimport android.view.accessibility.AccessibilityManager; 488a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 49d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganovimport android.view.accessibility.AccessibilityNodeProvider; 509cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganovimport android.view.animation.DecelerateInterpolator; 51a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganovimport android.view.inputmethod.EditorInfo; 52206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganovimport android.view.inputmethod.InputMethodManager; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 54b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganovimport com.android.internal.R; 55d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglioimport libcore.icu.LocaleData; 56b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov 57d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbyeimport java.lang.annotation.Retention; 58d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbyeimport java.lang.annotation.RetentionPolicy; 59d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganovimport java.util.ArrayList; 60d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganovimport java.util.Collections; 61d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganovimport java.util.List; 62d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglioimport java.util.Locale; 63d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 6468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook/** 650db4c3e0ed0e9a85f11db41285b9adb000c3f211Brian Duff * A widget that enables the user to select a number from a predefined range. 66d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * There are two flavors of this widget and which one is presented to the user 67d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * depends on the current theme. 68d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * <ul> 69d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * <li> 70d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * If the current theme is derived from {@link android.R.style#Theme} the widget 71d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * presents the current value as an editable input field with an increment button 72d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * above and a decrement button below. Long pressing the buttons allows for a quick 73d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * change of the current value. Tapping on the input field allows to type in 74d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * a desired value. 75d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * </li> 76d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * <li> 77d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * If the current theme is derived from {@link android.R.style#Theme_Holo} or 78d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * {@link android.R.style#Theme_Holo_Light} the widget presents the current 79d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * value as an editable input field with a lesser value above and a greater 80d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * value below. Tapping on the lesser or greater value selects it by animating 81d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * the number axis up or down to make the chosen value current. Flinging up 82d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * or down allows for multiple increments or decrements of the current value. 83d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Long pressing on the lesser and greater values also allows for a quick change 84d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * of the current value. Tapping on the current value allows to type in a 85d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * desired value. 86d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * </li> 87d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * </ul> 884bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 894bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * For an example of using this widget, see {@link android.widget.TimePicker}. 904bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 9168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 9268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook@Widget 9368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrookpublic class NumberPicker extends LinearLayout { 94fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 9568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 963f9c9eab7b41c409c3c7b503b89ad340e408b6a0Svetoslav Ganov * The number of items show in the selector wheel. 973f9c9eab7b41c409c3c7b503b89ad340e408b6a0Svetoslav Ganov */ 98d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private static final int SELECTOR_WHEEL_ITEM_COUNT = 3; 993f9c9eab7b41c409c3c7b503b89ad340e408b6a0Svetoslav Ganov 1003f9c9eab7b41c409c3c7b503b89ad340e408b6a0Svetoslav Ganov /** 101e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * The default update interval during long press. 102e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 103e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private static final long DEFAULT_LONG_PRESS_UPDATE_INTERVAL = 300; 104e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 105e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 106206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The index of the middle selector item. 10768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 108d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private static final int SELECTOR_MIDDLE_ITEM_INDEX = SELECTOR_WHEEL_ITEM_COUNT / 2; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 111206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The coefficient by which to adjust (divide) the max fling velocity. 11268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 113206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT = 8; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 115206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 116206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The the duration for adjusting the selector wheel. 117206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 118206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private static final int SELECTOR_ADJUSTMENT_DURATION_MILLIS = 800; 119fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 120206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1214213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov * The duration of scrolling while snapping to a given position. 122b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov */ 123fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov private static final int SNAP_SCROLL_DURATION = 300; 124b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov 125b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov /** 126b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * The strength of fading in the top and bottom while drawing the selector. 127206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 128b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private static final float TOP_AND_BOTTOM_FADING_EDGE_STRENGTH = 0.9f; 129206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 130206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 131b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * The default unscaled height of the selection divider. 132206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 133b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private static final int UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT = 2; 134206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 135206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 136d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The default unscaled distance between the selection dividers. 137b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov */ 138d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private static final int UNSCALED_DEFAULT_SELECTION_DIVIDERS_DISTANCE = 48; 139b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov 140b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov /** 141d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The resource id for the default layout. 142b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov */ 143d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private static final int DEFAULT_LAYOUT_RESOURCE_ID = R.layout.number_picker; 1449cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 1459cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 1469f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov * Constant for unspecified size. 1479f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov */ 1489f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov private static final int SIZE_UNSPECIFIED = -1; 1499f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov 1509f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov /** 151206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Use a custom NumberPicker formatting callback to use two-digit minutes 152206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * strings like "01". Keeping a static formatter etc. is the most efficient 153206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * way to do this; it avoids creating temporary objects on every call to 154206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * format(). 155206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 156d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio private static class TwoDigitFormatter implements NumberPicker.Formatter { 157206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final StringBuilder mBuilder = new StringBuilder(); 158206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 159d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio char mZeroDigit; 160d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio java.util.Formatter mFmt; 161206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 162206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov final Object[] mArgs = new Object[1]; 163206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 164d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio TwoDigitFormatter() { 165d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio final Locale locale = Locale.getDefault(); 166d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio init(locale); 167d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio } 168d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 169d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio private void init(Locale locale) { 170d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio mFmt = createFormatter(locale); 171d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio mZeroDigit = getZeroDigit(locale); 172d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio } 173d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 174e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String format(int value) { 175d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio final Locale currentLocale = Locale.getDefault(); 176d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio if (mZeroDigit != getZeroDigit(currentLocale)) { 177d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio init(currentLocale); 178d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio } 179206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mArgs[0] = value; 180206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mBuilder.delete(0, mBuilder.length()); 181206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mFmt.format("%02d", mArgs); 182206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return mFmt.toString(); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 184d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 185d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio private static char getZeroDigit(Locale locale) { 186d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio return LocaleData.get(locale).zeroDigit; 187d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio } 188d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 189d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio private java.util.Formatter createFormatter(Locale locale) { 190d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio return new java.util.Formatter(mBuilder, locale); 191d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio } 192d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio } 193d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 194d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio private static final TwoDigitFormatter sTwoDigitFormatter = new TwoDigitFormatter(); 195d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 196a65fe884d1bba4c64b961df27bd04e33e28a7209Fabrice Di Meglio /** 197a65fe884d1bba4c64b961df27bd04e33e28a7209Fabrice Di Meglio * @hide 198a65fe884d1bba4c64b961df27bd04e33e28a7209Fabrice Di Meglio */ 199a65fe884d1bba4c64b961df27bd04e33e28a7209Fabrice Di Meglio public static final Formatter getTwoDigitFormatter() { 200d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio return sTwoDigitFormatter; 201d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio } 202d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 203206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 204206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The increment button. 205206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 206206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final ImageButton mIncrementButton; 207206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 208206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 209206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The decrement button. 210206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 211206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final ImageButton mDecrementButton; 212206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 213206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 214206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The text for showing the current value. 215206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 216206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final EditText mInputText; 217206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 218206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 219d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The distance between the two selection dividers. 220d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 221d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private final int mSelectionDividersDistance; 222d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 223d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 224ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov * The min height of this widget. 225ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov */ 226ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov private final int mMinHeight; 227ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov 228ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov /** 229e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov * The max height of this widget. 230e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov */ 231e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov private final int mMaxHeight; 232e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov 233e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov /** 234e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov * The max width of this widget. 235e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov */ 236ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov private final int mMinWidth; 237ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov 238ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov /** 239ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov * The max width of this widget. 240ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov */ 241ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov private int mMaxWidth; 242ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov 243ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov /** 244ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov * Flag whether to compute the max width. 245ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov */ 246ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov private final boolean mComputeMaxWidth; 247e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov 248e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov /** 249206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The height of the text. 250206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 251206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int mTextSize; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 253206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 254b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * The height of the gap between text elements if the selector wheel. 255b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov */ 256b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private int mSelectorTextGapHeight; 257b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov 258b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov /** 259206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The values to be displayed instead the indices. 260206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String[] mDisplayedValues; 26268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 26368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 26468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Lower value of the range of numbers allowed for the NumberPicker 26568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 266e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mMinValue; 26768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 26868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 26968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Upper value of the range of numbers allowed for the NumberPicker 27068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 271e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mMaxValue; 27268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 27368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 27468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * Current value of this NumberPicker 27568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 276e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private int mValue; 27768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 27868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 279206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Listener to be notified upon current value change. 28068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 281cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov private OnValueChangeListener mOnValueChangeListener; 28250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 28350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 28450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * Listener to be notified upon scroll state change. 28550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 28650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov private OnScrollListener mOnScrollListener; 287206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 288206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 289206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Formatter for for displaying the current value. 290206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Formatter mFormatter; 292fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 293206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 294206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The speed for updating the value form long press. 295206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 296e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private long mLongPressUpdateInterval = DEFAULT_LONG_PRESS_UPDATE_INTERVAL; 297fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 29868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 299206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Cache for the string representation of selector indices. 300206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 301206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final SparseArray<String> mSelectorIndexToStringCache = new SparseArray<String>(); 302206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 303206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 304206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The selector indices whose value are show by the selector. 305206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 306d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private final int[] mSelectorIndices = new int[SELECTOR_WHEEL_ITEM_COUNT]; 307206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 308206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 309206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Paint} for drawing the selector. 310206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 311b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private final Paint mSelectorWheelPaint; 312206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 313206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 314232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov * The {@link Drawable} for pressed virtual (increment/decrement) buttons. 315232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov */ 316232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov private final Drawable mVirtualButtonPressedDrawable; 317232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 318232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov /** 319206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The height of a selector element (text + gap). 320206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 321206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectorElementHeight; 322206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 323206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 324206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The initial offset of the scroll selector. 325206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 326206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mInitialScrollOffset = Integer.MIN_VALUE; 327206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 328206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 329206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The current offset of the scroll selector. 330206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 331206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mCurrentScrollOffset; 332206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 333206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 334206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Scroller} responsible for flinging the selector. 335206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 336206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Scroller mFlingScroller; 337206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 338206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 339206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The {@link Scroller} responsible for adjusting the selector. 340206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 341206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final Scroller mAdjustScroller; 342206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 343206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 344206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The previous Y coordinate while scrolling the selector. 345206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 346206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mPreviousScrollerY; 347206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 348206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 349206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Handle to the reusable command for setting the input text selection. 350206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 351206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private SetSelectionCommand mSetSelectionCommand; 352206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 353206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 354b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * Handle to the reusable command for changing the current value from long 355b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * press by one. 356206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 357b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private ChangeCurrentByOneFromLongPressCommand mChangeCurrentByOneFromLongPressCommand; 358206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 359206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 360d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Command for beginning an edit of the current value via IME on long press. 361b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov */ 362d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private BeginSoftInputOnLongPressCommand mBeginSoftInputOnLongPressCommand; 363b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov 364b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov /** 365206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The Y position of the last down event. 366206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 367206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private float mLastDownEventY; 368206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 369206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 370d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The time of the last down event. 371206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 372d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private long mLastDownEventTime; 373206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 374206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 375d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The Y position of the last down or move event. 376206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 377d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private float mLastDownOrMoveEventY; 378206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 379206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 380206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Determines speed during touch scrolling. 381206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 382206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private VelocityTracker mVelocityTracker; 383206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 384206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 385206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledTouchSlop() 386206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 387206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mTouchSlop; 388206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 389206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 390206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledMinimumFlingVelocity() 391206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 392206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mMinimumFlingVelocity; 393206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 394206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 395206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @see ViewConfiguration#getScaledMaximumFlingVelocity() 396206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 397206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mMaximumFlingVelocity; 398206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 399206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 400206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flag whether the selector should wrap around. 401206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 402e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov private boolean mWrapSelectorWheel; 403206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 404206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 405206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The back ground color used to optimize scroller fading. 40668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 407206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private final int mSolidColor; 408206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 409206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 410d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Flag whether this widget has a selector wheel. 4114243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov */ 412d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private final boolean mHasSelectorWheel; 4134243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov 4144243dc394d89a93cb207efa36e9755c2424d688bSvetoslav Ganov /** 4159cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * Divider for showing item to be selected while scrolling 4169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 4179cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final Drawable mSelectionDivider; 4189cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 4199cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 4209cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * The height of the selection divider. 4219cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 4229cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private final int mSelectionDividerHeight; 4239cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 4249cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 425d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The current scroll state of the number picker. 426206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 427d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE; 428206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 429206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 430d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Flag whether to ignore move events - we ignore such when we show in IME 431d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * to prevent the content from scrolling. 43250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 43346a27efe9528ac3c5b37726707844e7c868815acSvetoslav private boolean mIgnoreMoveEvents; 43450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 43550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 43646a27efe9528ac3c5b37726707844e7c868815acSvetoslav * Flag whether to perform a click on tap. 4379cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov */ 43846a27efe9528ac3c5b37726707844e7c868815acSvetoslav private boolean mPerformClickOnTap; 4399cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 4409cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov /** 441d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The top of the top selection divider. 442b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov */ 443d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private int mTopSelectionDividerTop; 444b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov 445b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov /** 446d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The bottom of the bottom selection divider. 447a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov */ 448d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private int mBottomSelectionDividerBottom; 449d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 450d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 451d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The virtual id of the last hovered child. 452d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 453d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private int mLastHoveredChildVirtualViewId; 454d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 455d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 456232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov * Whether the increment virtual button is pressed. 457232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov */ 458232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov private boolean mIncrementVirtualButtonPressed; 459232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 460232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov /** 461232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov * Whether the decrement virtual button is pressed. 462232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov */ 463232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov private boolean mDecrementVirtualButtonPressed; 464232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 465232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov /** 466d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Provider to report to clients the semantic structure of this widget. 467d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 468d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private AccessibilityNodeProviderImpl mAccessibilityNodeProvider; 469a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov 470a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov /** 471232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov * Helper class for managing pressed state of the virtual buttons. 472232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov */ 473232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov private final PressedStateHelper mPressedStateHelper; 474232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 475232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov /** 4765dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov * The keycode of the last handled DPAD down event. 4775dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov */ 4785dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov private int mLastHandledDownDpadKeyCode = -1; 4795dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov 4805dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov /** 4819eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout * If true then the selector wheel is hidden until the picker has focus. 4829eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout */ 4839eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout private boolean mHideWheelUntilFocused; 4849eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout 4859eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout /** 486e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface to listen for changes of the current value. 487206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 488cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov public interface OnValueChangeListener { 489e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 490206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 4914bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Called upon a change of the current value. 4924bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 493206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param picker The NumberPicker associated with this listener. 494206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param oldVal The previous value. 495206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param newVal The new value. 496206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 497e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov void onValueChange(NumberPicker picker, int oldVal, int newVal); 498206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 499206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 500206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 501e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface to listen for the picker scroll state. 50250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 50350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public interface OnScrollListener { 504d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye /** @hide */ 505d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye @IntDef({SCROLL_STATE_IDLE, SCROLL_STATE_TOUCH_SCROLL, SCROLL_STATE_FLING}) 506d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye @Retention(RetentionPolicy.SOURCE) 507d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye public @interface ScrollState {} 50850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 50950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 51050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The view is not scrolling. 51150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 51250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_IDLE = 0; 51350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 51450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 515d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * The user is scrolling using touch, and his finger is still on the screen. 51650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 51750f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_TOUCH_SCROLL = 1; 51850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 51950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 52050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * The user had previously been scrolling using touch and performed a fling. 52150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 52250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public static int SCROLL_STATE_FLING = 2; 52350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 52450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 525e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Callback invoked while the number picker scroll state has changed. 52650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 527e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param view The view whose scroll state is being reported. 528e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param scrollState The current scroll state. One of 529e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_IDLE}, 530e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_TOUCH_SCROLL} or 531e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link #SCROLL_STATE_IDLE}. 53250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 533d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye public void onScrollStateChange(NumberPicker view, @ScrollState int scrollState); 53450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 53550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 53650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 537e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Interface used to format current value into a string for presentation. 538206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 539206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public interface Formatter { 5404bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 5414bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 542e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Formats a string representation of the current value. 5434bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 5444bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param value The currently selected value. 5454bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @return A formatted string representation. 5464bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 547e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String format(int value); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 55068f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 5514bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Create a new number picker. 5524bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 5534bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param context The application environment. 5544bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 5554bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public NumberPicker(Context context) { 5564bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov this(context, null); 5574bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 5584bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 5594bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 5604bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Create a new number picker. 561206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 562206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param context The application environment. 563206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param attrs A collection of attributes. 56468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public NumberPicker(Context context, AttributeSet attrs) { 566206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov this(context, attrs, R.attr.numberPickerStyle); 567206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 568206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 569206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 570206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Create a new number picker 571206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 572206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param context the application environment. 573206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @param attrs a collection of attributes. 574617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 575617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * reference to a style resource that supplies default values for 576617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * the view. Can be 0 to not look for defaults. 577206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 578617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public NumberPicker(Context context, AttributeSet attrs, int defStyleAttr) { 579617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 580617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 581617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 582617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette /** 583617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * Create a new number picker 584617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * 585617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param context the application environment. 586617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param attrs a collection of attributes. 587617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 588617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * reference to a style resource that supplies default values for 589617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * the view. Can be 0 to not look for defaults. 590617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleRes A resource identifier of a style resource that 591617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * supplies default values for the view, used only if 592617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * defStyleAttr is 0 or can not be found in the theme. Can be 0 593617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * to not look for defaults. 594617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette */ 595617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public NumberPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 596617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 597206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 598206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // process style attributes 599617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette final TypedArray attributesArray = context.obtainStyledAttributes( 600617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette attrs, R.styleable.NumberPicker, defStyleAttr, defStyleRes); 601d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int layoutResId = attributesArray.getResourceId( 602d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.styleable.NumberPicker_internalLayout, DEFAULT_LAYOUT_RESOURCE_ID); 603d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 604d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mHasSelectorWheel = (layoutResId != DEFAULT_LAYOUT_RESOURCE_ID); 605d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 6069eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout mHideWheelUntilFocused = attributesArray.getBoolean( 6079eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout R.styleable.NumberPicker_hideWheelUntilFocused, false); 6089eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout 609206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSolidColor = attributesArray.getColor(R.styleable.NumberPicker_solidColor, 0); 610d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 6119cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider = attributesArray.getDrawable(R.styleable.NumberPicker_selectionDivider); 612d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 613d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int defSelectionDividerHeight = (int) TypedValue.applyDimension( 614d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT, 6159cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov getResources().getDisplayMetrics()); 6169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDividerHeight = attributesArray.getDimensionPixelSize( 6179cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight); 618d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 619d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int defSelectionDividerDistance = (int) TypedValue.applyDimension( 620d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_SELECTION_DIVIDERS_DISTANCE, 621d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov getResources().getDisplayMetrics()); 622d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mSelectionDividersDistance = attributesArray.getDimensionPixelSize( 623d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.styleable.NumberPicker_selectionDividersDistance, defSelectionDividerDistance); 624d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 625e8331bd2e7ad3d62140143cafba3ff69be028557Svetoslav Ganov mMinHeight = attributesArray.getDimensionPixelSize( 626e8331bd2e7ad3d62140143cafba3ff69be028557Svetoslav Ganov R.styleable.NumberPicker_internalMinHeight, SIZE_UNSPECIFIED); 627d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 628e8331bd2e7ad3d62140143cafba3ff69be028557Svetoslav Ganov mMaxHeight = attributesArray.getDimensionPixelSize( 629e8331bd2e7ad3d62140143cafba3ff69be028557Svetoslav Ganov R.styleable.NumberPicker_internalMaxHeight, SIZE_UNSPECIFIED); 6309f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov if (mMinHeight != SIZE_UNSPECIFIED && mMaxHeight != SIZE_UNSPECIFIED 6319f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov && mMinHeight > mMaxHeight) { 632ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov throw new IllegalArgumentException("minHeight > maxHeight"); 633ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 634d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 635d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mMinWidth = attributesArray.getDimensionPixelSize( 636d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.styleable.NumberPicker_internalMinWidth, SIZE_UNSPECIFIED); 637d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 638d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mMaxWidth = attributesArray.getDimensionPixelSize( 639d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov R.styleable.NumberPicker_internalMaxWidth, SIZE_UNSPECIFIED); 6409f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov if (mMinWidth != SIZE_UNSPECIFIED && mMaxWidth != SIZE_UNSPECIFIED 6419f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov && mMinWidth > mMaxWidth) { 642ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov throw new IllegalArgumentException("minWidth > maxWidth"); 643ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 644d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 645f7c83bc4d3e1996b491824902a6a0f98ac69bedeSvetoslav Ganov mComputeMaxWidth = (mMaxWidth == SIZE_UNSPECIFIED); 646206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 647232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mVirtualButtonPressedDrawable = attributesArray.getDrawable( 648232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov R.styleable.NumberPicker_virtualButtonPressedDrawable); 649232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 650d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov attributesArray.recycle(); 6519cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 652232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mPressedStateHelper = new PressedStateHelper(); 653232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 654206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // By default Linearlayout that we extend is not drawn. This is 655206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // its draw() method is not called but dispatchDraw() is called 656206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // directly (see ViewGroup.drawChild()). However, this class uses 657206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // the fading edge effect implemented by View and we need our 658206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // draw() method to be called. Therefore, we declare we will draw. 659d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov setWillNotDraw(!mHasSelectorWheel); 660206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 661206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( 662206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Context.LAYOUT_INFLATER_SERVICE); 663d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov inflater.inflate(layoutResId, this, true); 66468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 665206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov OnClickListener onClickListener = new OnClickListener() { 66668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook public void onClick(View v) { 667b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov hideSoftInput(); 668206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 669206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (v.getId() == R.id.increment) { 670d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov changeValueByOne(true); 671206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 672d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov changeValueByOne(false); 67368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 67468f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 67568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook }; 67668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 677206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov OnLongClickListener onLongClickListener = new OnLongClickListener() { 678206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onLongClick(View v) { 679b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov hideSoftInput(); 680206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.clearFocus(); 681206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (v.getId() == R.id.increment) { 682d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov postChangeCurrentByOneFromLongPress(true, 0); 683206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 684d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov postChangeCurrentByOneFromLongPress(false, 0); 685206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 686206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 687206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 688206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }; 68968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 690206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // increment button 691d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 692d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mIncrementButton = (ImageButton) findViewById(R.id.increment); 693d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mIncrementButton.setOnClickListener(onClickListener); 694d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mIncrementButton.setOnLongClickListener(onLongClickListener); 695d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 696d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mIncrementButton = null; 697d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 698206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 699206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // decrement button 700d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 701d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mDecrementButton = (ImageButton) findViewById(R.id.decrement); 702d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mDecrementButton.setOnClickListener(onClickListener); 703d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mDecrementButton.setOnLongClickListener(onLongClickListener); 704d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 705d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mDecrementButton = null; 706d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 707206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 708206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // input text 709012dd5a461f18a2e5dad38c60282fac1c21ff7feSvetoslav Ganov mInputText = (EditText) findViewById(R.id.numberpicker_input); 710206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setOnFocusChangeListener(new OnFocusChangeListener() { 711206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void onFocusChange(View v, boolean hasFocus) { 712a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov if (hasFocus) { 713a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov mInputText.selectAll(); 714a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov } else { 715a53efe9923bedab4fe5d578f32eaff308e5b9e76Svetoslav Ganov mInputText.setSelection(0, 0); 716206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov validateInputTextView(v); 71768f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 71868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 719206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 720206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setFilters(new InputFilter[] { 721206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov new InputTextFilter() 722206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov }); 72368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 724206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 725a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov mInputText.setImeOptions(EditorInfo.IME_ACTION_DONE); 726206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 727206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // initialize constants 728206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ViewConfiguration configuration = ViewConfiguration.get(context); 729206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTouchSlop = configuration.getScaledTouchSlop(); 730206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); 731206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity() 732206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov / SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT; 733206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mTextSize = (int) mInputText.getTextSize(); 734206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 735206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the selector wheel paint 736206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Paint paint = new Paint(); 737206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setAntiAlias(true); 738206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTextAlign(Align.CENTER); 739206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTextSize(mTextSize); 740206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setTypeface(mInputText.getTypeface()); 741206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ColorStateList colors = mInputText.getTextColors(); 742206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int color = colors.getColorForState(ENABLED_STATE_SET, Color.WHITE); 743206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov paint.setColor(color); 744b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov mSelectorWheelPaint = paint; 745206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 746206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // create the fling and adjust scrollers 747bf80562d22b2bbe7944d80d0524c69d0238010cbSvetoslav Ganov mFlingScroller = new Scroller(getContext(), null, true); 7489cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mAdjustScroller = new Scroller(getContext(), new DecelerateInterpolator(2.5f)); 749fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 750206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 7514213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov 7524213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov // If not explicitly specified this view is important for accessibility. 7534213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 7544213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 7554213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov } 756206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 757206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 758206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 7599cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 760d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 761d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov super.onLayout(changed, left, top, right, bottom); 762d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return; 763d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 764ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int msrdWdth = getMeasuredWidth(); 765ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int msrdHght = getMeasuredHeight(); 766ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov 767ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov // Input text centered horizontally. 768ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int inptTxtMsrdWdth = mInputText.getMeasuredWidth(); 769ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int inptTxtMsrdHght = mInputText.getMeasuredHeight(); 770ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int inptTxtLeft = (msrdWdth - inptTxtMsrdWdth) / 2; 771ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int inptTxtTop = (msrdHght - inptTxtMsrdHght) / 2; 772ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int inptTxtRight = inptTxtLeft + inptTxtMsrdWdth; 773ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int inptTxtBottom = inptTxtTop + inptTxtMsrdHght; 774ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov mInputText.layout(inptTxtLeft, inptTxtTop, inptTxtRight, inptTxtBottom); 775ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov 776d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (changed) { 777b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov // need to do all this when we know our size 778b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov initializeSelectorWheel(); 779b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov initializeFadingEdges(); 780d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mTopSelectionDividerTop = (getHeight() - mSelectionDividersDistance) / 2 781d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov - mSelectionDividerHeight; 782d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mBottomSelectionDividerBottom = mTopSelectionDividerTop + 2 * mSelectionDividerHeight 783d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov + mSelectionDividersDistance; 784b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } 785206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 786206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 787206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 788e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 789d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 790d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov super.onMeasure(widthMeasureSpec, heightMeasureSpec); 791d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return; 792d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 793698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov // Try greedily to fit the max width and height. 794698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov final int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMaxWidth); 795698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight); 796ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec); 797698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov // Flag if we are measured with width or height less than the respective min. 7989f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov final int widthSize = resolveSizeAndStateRespectingMinSize(mMinWidth, getMeasuredWidth(), 7999f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov widthMeasureSpec); 8009f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov final int heightSize = resolveSizeAndStateRespectingMinSize(mMinHeight, getMeasuredHeight(), 8019f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov heightMeasureSpec); 802698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov setMeasuredDimension(widthSize, heightSize); 803e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov } 804e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov 805d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 806d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Move to the final position of a scroller. Ensures to force finish the scroller 807d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * and if it is not at its final position a scroll of the selector wheel is 808d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * performed to fast forward to the final position. 809d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * 810d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * @param scroller The scroller to whose final position to get. 811d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * @return True of the a move was performed, i.e. the scroller was not in final position. 812d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 813d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private boolean moveToFinalScrollerPosition(Scroller scroller) { 814d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov scroller.forceFinished(true); 815d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int amountToScroll = scroller.getFinalY() - scroller.getCurrY(); 816d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int futureScrollOffset = (mCurrentScrollOffset + amountToScroll) % mSelectorElementHeight; 817d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int overshootAdjustment = mInitialScrollOffset - futureScrollOffset; 818d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (overshootAdjustment != 0) { 819d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (Math.abs(overshootAdjustment) > mSelectorElementHeight / 2) { 820d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (overshootAdjustment > 0) { 821d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov overshootAdjustment -= mSelectorElementHeight; 822d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 823d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov overshootAdjustment += mSelectorElementHeight; 824d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 825d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 826d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov amountToScroll += overshootAdjustment; 827d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov scrollBy(0, amountToScroll); 828d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return true; 829d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 830d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return false; 831d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 832d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 833e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov @Override 834206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean onInterceptTouchEvent(MotionEvent event) { 835d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel || !isEnabled()) { 83651c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return false; 83751c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 838d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int action = event.getActionMasked(); 839d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (action) { 840d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case MotionEvent.ACTION_DOWN: { 841206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 842d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mInputText.setVisibility(View.INVISIBLE); 843d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mLastDownOrMoveEventY = mLastDownEventY = event.getY(); 844d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mLastDownEventTime = event.getEventTime(); 84546a27efe9528ac3c5b37726707844e7c868815acSvetoslav mIgnoreMoveEvents = false; 84646a27efe9528ac3c5b37726707844e7c868815acSvetoslav mPerformClickOnTap = false; 847232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov // Handle pressed state before any state change. 848232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (mLastDownEventY < mTopSelectionDividerTop) { 849232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { 850232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mPressedStateHelper.buttonPressDelayed( 851232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov PressedStateHelper.BUTTON_DECREMENT); 852232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 853232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } else if (mLastDownEventY > mBottomSelectionDividerBottom) { 854232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { 855232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mPressedStateHelper.buttonPressDelayed( 856232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov PressedStateHelper.BUTTON_INCREMENT); 857232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 858232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 859232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov // Make sure we support flinging inside scrollables. 86083dc45c65988e9b86e156d59f59ede48195ed1d5Svetoslav Ganov getParent().requestDisallowInterceptTouchEvent(true); 861d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mFlingScroller.isFinished()) { 862d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mFlingScroller.forceFinished(true); 863d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mAdjustScroller.forceFinished(true); 864d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 865d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else if (!mAdjustScroller.isFinished()) { 866d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mFlingScroller.forceFinished(true); 867d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mAdjustScroller.forceFinished(true); 868d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else if (mLastDownEventY < mTopSelectionDividerTop) { 869b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov hideSoftInput(); 870d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov postChangeCurrentByOneFromLongPress( 871d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov false, ViewConfiguration.getLongPressTimeout()); 872d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else if (mLastDownEventY > mBottomSelectionDividerBottom) { 873b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov hideSoftInput(); 874d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov postChangeCurrentByOneFromLongPress( 875d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov true, ViewConfiguration.getLongPressTimeout()); 876d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 87746a27efe9528ac3c5b37726707844e7c868815acSvetoslav mPerformClickOnTap = true; 878d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov postBeginSoftInputOnLongPressCommand(); 879206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 880d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return true; 881d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 882206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 883206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return false; 884206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 885206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 886206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 887d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov public boolean onTouchEvent(MotionEvent event) { 888d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!isEnabled() || !mHasSelectorWheel) { 88951c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov return false; 89051c52edad7d40697d7fb2a091f850506fa897643Svetoslav Ganov } 891206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mVelocityTracker == null) { 892206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = VelocityTracker.obtain(); 893206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 894d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mVelocityTracker.addMovement(event); 895d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int action = event.getActionMasked(); 896206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov switch (action) { 897d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case MotionEvent.ACTION_MOVE: { 89846a27efe9528ac3c5b37726707844e7c868815acSvetoslav if (mIgnoreMoveEvents) { 899d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov break; 900d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 901d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov float currentMoveY = event.getY(); 902d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 903206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); 904206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (deltaDownY > mTouchSlop) { 905d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeAllCallbacks(); 9069cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); 907206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 908d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 909232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov int deltaMoveY = (int) ((currentMoveY - mLastDownOrMoveEventY)); 910d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov scrollBy(0, deltaMoveY); 911d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov invalidate(); 912206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 913d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mLastDownOrMoveEventY = currentMoveY; 914d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 915d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case MotionEvent.ACTION_UP: { 916d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeBeginSoftInputCommand(); 917d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeChangeCurrentByOneFromLongPress(); 918232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mPressedStateHelper.cancel(); 919206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov VelocityTracker velocityTracker = mVelocityTracker; 920206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); 921206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int initialVelocity = (int) velocityTracker.getYVelocity(); 922206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (Math.abs(initialVelocity) > mMinimumFlingVelocity) { 923232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov fling(initialVelocity); 9249cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); 925206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 926d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int eventY = (int) event.getY(); 927d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int deltaMoveY = (int) Math.abs(eventY - mLastDownEventY); 928d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov long deltaTime = event.getEventTime() - mLastDownEventTime; 929d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (deltaMoveY <= mTouchSlop && deltaTime < ViewConfiguration.getTapTimeout()) { 93046a27efe9528ac3c5b37726707844e7c868815acSvetoslav if (mPerformClickOnTap) { 93146a27efe9528ac3c5b37726707844e7c868815acSvetoslav mPerformClickOnTap = false; 93246a27efe9528ac3c5b37726707844e7c868815acSvetoslav performClick(); 933d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 934d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int selectorIndexOffset = (eventY / mSelectorElementHeight) 935d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov - SELECTOR_MIDDLE_ITEM_INDEX; 936d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (selectorIndexOffset > 0) { 937d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov changeValueByOne(true); 938232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mPressedStateHelper.buttonTapped( 939232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov PressedStateHelper.BUTTON_INCREMENT); 940d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else if (selectorIndexOffset < 0) { 941d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov changeValueByOne(false); 942232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mPressedStateHelper.buttonTapped( 943232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov PressedStateHelper.BUTTON_DECREMENT); 944d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 945206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 946206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 947d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov ensureScrollWheelAdjusted(); 948206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 949d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 950206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 951206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker.recycle(); 952206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mVelocityTracker = null; 953d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 954206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 955206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return true; 956206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 957206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 958206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 959206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTouchEvent(MotionEvent event) { 960b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov final int action = event.getActionMasked(); 961b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov switch (action) { 962b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov case MotionEvent.ACTION_CANCEL: 963b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov case MotionEvent.ACTION_UP: 964b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov removeAllCallbacks(); 965b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov break; 966206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 967206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTouchEvent(event); 968206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 969206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 970206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 971206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchKeyEvent(KeyEvent event) { 972d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int keyCode = event.getKeyCode(); 973d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (keyCode) { 974d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case KeyEvent.KEYCODE_DPAD_CENTER: 975d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case KeyEvent.KEYCODE_ENTER: 976d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeAllCallbacks(); 977d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov break; 9785dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov case KeyEvent.KEYCODE_DPAD_DOWN: 9795dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov case KeyEvent.KEYCODE_DPAD_UP: 9805dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov if (!mHasSelectorWheel) { 9815dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov break; 9825dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov } 9835dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov switch (event.getAction()) { 9845dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov case KeyEvent.ACTION_DOWN: 9859eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout if (mWrapSelectorWheel || ((keyCode == KeyEvent.KEYCODE_DPAD_DOWN) 9869eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout ? getValue() < getMaxValue() : getValue() > getMinValue())) { 9875dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov requestFocus(); 9885dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov mLastHandledDownDpadKeyCode = keyCode; 9895dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov removeAllCallbacks(); 9905dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov if (mFlingScroller.isFinished()) { 99186cf0cdfe14ce9606d42671b2961081f3220a789Justin Mattson changeValueByOne(keyCode == KeyEvent.KEYCODE_DPAD_DOWN); 9925dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov } 9935dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov return true; 9945dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov } 9955dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov break; 9965dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov case KeyEvent.ACTION_UP: 9975dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov if (mLastHandledDownDpadKeyCode == keyCode) { 9985dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov mLastHandledDownDpadKeyCode = -1; 9995dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov return true; 10005dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov } 10015dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov break; 10025dc21d9b340fe2c1cb4c37435d8a29429cf3f79eSvetoslav Ganov } 1003206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1004206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchKeyEvent(event); 1005206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1006206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1007206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1008206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public boolean dispatchTrackballEvent(MotionEvent event) { 1009d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int action = event.getActionMasked(); 1010d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (action) { 1011d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case MotionEvent.ACTION_CANCEL: 1012d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case MotionEvent.ACTION_UP: 1013d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeAllCallbacks(); 1014d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov break; 1015206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1016206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return super.dispatchTrackballEvent(event); 1017206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1020d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov protected boolean dispatchHoverEvent(MotionEvent event) { 1021d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 1022d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return super.dispatchHoverEvent(event); 1023d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1024d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (AccessibilityManager.getInstance(mContext).isEnabled()) { 1025d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int eventY = (int) event.getY(); 1026d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int hoveredVirtualViewId; 1027d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (eventY < mTopSelectionDividerTop) { 1028d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_DECREMENT; 1029d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else if (eventY > mBottomSelectionDividerBottom) { 1030d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_INCREMENT; 1031d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 1032d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_INPUT; 1033d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1034d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov final int action = event.getActionMasked(); 1035d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov AccessibilityNodeProviderImpl provider = 1036d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov (AccessibilityNodeProviderImpl) getAccessibilityNodeProvider(); 1037d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (action) { 1038d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case MotionEvent.ACTION_HOVER_ENTER: { 1039d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId, 1040d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 1041d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mLastHoveredChildVirtualViewId = hoveredVirtualViewId; 1042791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov provider.performAction(hoveredVirtualViewId, 1043791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); 1044d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 1045d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case MotionEvent.ACTION_HOVER_MOVE: { 1046d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mLastHoveredChildVirtualViewId != hoveredVirtualViewId 1047d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov && mLastHoveredChildVirtualViewId != View.NO_ID) { 1048d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov provider.sendAccessibilityEventForVirtualView( 1049d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mLastHoveredChildVirtualViewId, 1050d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 1051d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId, 1052d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 1053d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mLastHoveredChildVirtualViewId = hoveredVirtualViewId; 1054791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov provider.performAction(hoveredVirtualViewId, 1055791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); 1056d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1057d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 1058d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case MotionEvent.ACTION_HOVER_EXIT: { 1059d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId, 1060d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 1061d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mLastHoveredChildVirtualViewId = View.NO_ID; 1062d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 1063d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1064206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1065d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return false; 1066d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1067d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 1068d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov @Override 1069d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov public void computeScroll() { 1070206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov Scroller scroller = mFlingScroller; 1071206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 1072206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller = mAdjustScroller; 1073206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 1074206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1075206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1076206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1077206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scroller.computeScrollOffset(); 1078206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int currentScrollerY = scroller.getCurrY(); 1079206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mPreviousScrollerY == 0) { 1080206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = scroller.getStartY(); 1081206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1082206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollBy(0, currentScrollerY - mPreviousScrollerY); 1083206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = currentScrollerY; 1084206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller.isFinished()) { 1085206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov onScrollerFinished(scroller); 1086206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1087206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1090fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setEnabled(boolean enabled) { 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setEnabled(enabled); 1094d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 1095d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mIncrementButton.setEnabled(enabled); 1096d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1097d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 1098d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mDecrementButton.setEnabled(enabled); 1099d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1100206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setEnabled(enabled); 1101206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1102206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1103206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1104206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void scrollBy(int x, int y) { 1105b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov int[] selectorIndices = mSelectorIndices; 110634c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (!mWrapSelectorWheel && y > 0 110734c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { 1108206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 1109206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1110206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 111134c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov if (!mWrapSelectorWheel && y < 0 111234c0688ceafbeef2648bd2287b3b3c3801679448Svetoslav Ganov && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { 1113206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 1114206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1115206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1116206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += y; 1117b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset > mSelectorTextGapHeight) { 1118206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset -= mSelectorElementHeight; 1119206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov decrementSelectorIndices(selectorIndices); 1120d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov setValueInternal(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX], true); 1121b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { 1122206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 1123206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1124206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1125b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov while (mCurrentScrollOffset - mInitialScrollOffset < -mSelectorTextGapHeight) { 1126206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset += mSelectorElementHeight; 1127b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov incrementSelectorIndices(selectorIndices); 1128d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov setValueInternal(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX], true); 1129b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { 1130206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 1131206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1132206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1134fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 11354bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov @Override 1136fd63917ed31fbf425362d209eff72d5e64c5bb8aAlan Viverette protected int computeVerticalScrollOffset() { 11375ba99f58b1e90a6faaf5e84d713e10cf0323ac96Alan Viverette return mCurrentScrollOffset; 11385ba99f58b1e90a6faaf5e84d713e10cf0323ac96Alan Viverette } 11395ba99f58b1e90a6faaf5e84d713e10cf0323ac96Alan Viverette 11405ba99f58b1e90a6faaf5e84d713e10cf0323ac96Alan Viverette @Override 1141fd63917ed31fbf425362d209eff72d5e64c5bb8aAlan Viverette protected int computeVerticalScrollRange() { 1142fd63917ed31fbf425362d209eff72d5e64c5bb8aAlan Viverette return (mMaxValue - mMinValue + 1) * mSelectorElementHeight; 1143fd63917ed31fbf425362d209eff72d5e64c5bb8aAlan Viverette } 1144fd63917ed31fbf425362d209eff72d5e64c5bb8aAlan Viverette 1145fd63917ed31fbf425362d209eff72d5e64c5bb8aAlan Viverette @Override 1146fd63917ed31fbf425362d209eff72d5e64c5bb8aAlan Viverette protected int computeVerticalScrollExtent() { 1147fd63917ed31fbf425362d209eff72d5e64c5bb8aAlan Viverette return getHeight(); 11485ba99f58b1e90a6faaf5e84d713e10cf0323ac96Alan Viverette } 11495ba99f58b1e90a6faaf5e84d713e10cf0323ac96Alan Viverette 11505ba99f58b1e90a6faaf5e84d713e10cf0323ac96Alan Viverette @Override 11514bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public int getSolidColor() { 11524bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov return mSolidColor; 11534bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 11544bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 115568f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 11564bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the listener to be notified on change of the current value. 1157206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 1158e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param onValueChangedListener The listener. 115968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1160cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov public void setOnValueChangedListener(OnValueChangeListener onValueChangedListener) { 1161cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mOnValueChangeListener = onValueChangedListener; 116250f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 116350f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 116450f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 11654bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set listener to be notified for scroll state changes. 116650f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov * 1167e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param onScrollListener The listener. 116850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 116950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov public void setOnScrollListener(OnScrollListener onScrollListener) { 117050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov mOnScrollListener = onScrollListener; 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1172fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 117368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 11744bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Set the formatter to be used for formatting the current value. 11754bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 1176e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Note: If you have provided alternative values for the values this 1177e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * formatter is never invoked. 11784bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 1179206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 1180e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param formatter The formatter object. If formatter is <code>null</code>, 1181e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link String#valueOf(int)} will be used. 1182d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov *@see #setDisplayedValues(String[]) 118368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFormatter(Formatter formatter) { 1185e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (formatter == mFormatter) { 1186e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1187e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFormatter = formatter; 1189b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov initializeSelectorWheelIndices(); 11909cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov updateInputTextView(); 1191206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1192206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1193206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1194e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Set the current value for the number picker. 11954bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * <p> 1196e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMinValue()} and 1197e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the 1198e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMinValue()} value. 1199e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 1200e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 1201e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMinValue()} and 1202e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the 1203e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMaxValue()} value. 1204e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 1205e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 1206e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMaxValue()} and 1207e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the 1208e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMaxValue()} value. 1209e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 1210e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 1211e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * If the argument is less than the {@link NumberPicker#getMaxValue()} and 1212e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the 1213e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * current value is set to the {@link NumberPicker#getMinValue()} value. 12144bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * </p> 1215206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 1216e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param value The current value. 12174bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @see #setWrapSelectorWheel(boolean) 1218e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setMinValue(int) 1219e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #setMaxValue(int) 1220206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1221e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setValue(int value) { 1222d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov setValueInternal(value, false); 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1224fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 122546a27efe9528ac3c5b37726707844e7c868815acSvetoslav @Override 122646a27efe9528ac3c5b37726707844e7c868815acSvetoslav public boolean performClick() { 122746a27efe9528ac3c5b37726707844e7c868815acSvetoslav if (!mHasSelectorWheel) { 122846a27efe9528ac3c5b37726707844e7c868815acSvetoslav return super.performClick(); 122946a27efe9528ac3c5b37726707844e7c868815acSvetoslav } else if (!super.performClick()) { 123046a27efe9528ac3c5b37726707844e7c868815acSvetoslav showSoftInput(); 123146a27efe9528ac3c5b37726707844e7c868815acSvetoslav } 123246a27efe9528ac3c5b37726707844e7c868815acSvetoslav return true; 123346a27efe9528ac3c5b37726707844e7c868815acSvetoslav } 123446a27efe9528ac3c5b37726707844e7c868815acSvetoslav 123546a27efe9528ac3c5b37726707844e7c868815acSvetoslav @Override 123646a27efe9528ac3c5b37726707844e7c868815acSvetoslav public boolean performLongClick() { 123746a27efe9528ac3c5b37726707844e7c868815acSvetoslav if (!mHasSelectorWheel) { 123846a27efe9528ac3c5b37726707844e7c868815acSvetoslav return super.performLongClick(); 123946a27efe9528ac3c5b37726707844e7c868815acSvetoslav } else if (!super.performLongClick()) { 124046a27efe9528ac3c5b37726707844e7c868815acSvetoslav showSoftInput(); 124146a27efe9528ac3c5b37726707844e7c868815acSvetoslav mIgnoreMoveEvents = true; 124246a27efe9528ac3c5b37726707844e7c868815acSvetoslav } 124346a27efe9528ac3c5b37726707844e7c868815acSvetoslav return true; 124446a27efe9528ac3c5b37726707844e7c868815acSvetoslav } 124546a27efe9528ac3c5b37726707844e7c868815acSvetoslav 124668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1247d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Shows the soft input for its input text. 1248d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 1249d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void showSoftInput() { 1250d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); 1251d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (inputMethodManager != null) { 1252d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mHasSelectorWheel) { 1253d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mInputText.setVisibility(View.VISIBLE); 1254d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1255d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mInputText.requestFocus(); 1256d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov inputMethodManager.showSoftInput(mInputText, 0); 1257d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1258d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1259d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 1260d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 1261d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Hides the soft input if it is active for the input text. 1262b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov */ 1263b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov private void hideSoftInput() { 1264b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); 1265b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov if (inputMethodManager != null && inputMethodManager.isActive(mInputText)) { 1266b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 1267d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mHasSelectorWheel) { 1268d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mInputText.setVisibility(View.INVISIBLE); 1269d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1270b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov } 1271b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov } 1272b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov 1273b52d9729bfb2ef7ad50d9a5125ebf3a8322429a9Svetoslav Ganov /** 1274ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov * Computes the max width if no such specified as an attribute. 1275ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov */ 1276ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov private void tryComputeMaxWidth() { 1277ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov if (!mComputeMaxWidth) { 1278ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov return; 1279ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1280ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov int maxTextWidth = 0; 1281ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov if (mDisplayedValues == null) { 1282ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov float maxDigitWidth = 0; 1283ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov for (int i = 0; i <= 9; i++) { 1284d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio final float digitWidth = mSelectorWheelPaint.measureText(formatNumberWithLocale(i)); 1285ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov if (digitWidth > maxDigitWidth) { 1286ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov maxDigitWidth = digitWidth; 1287ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1288ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1289ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov int numberOfDigits = 0; 1290ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov int current = mMaxValue; 1291ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov while (current > 0) { 1292ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov numberOfDigits++; 1293ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov current = current / 10; 1294ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1295ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov maxTextWidth = (int) (numberOfDigits * maxDigitWidth); 1296ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } else { 1297ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int valueCount = mDisplayedValues.length; 1298ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov for (int i = 0; i < valueCount; i++) { 1299ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final float textWidth = mSelectorWheelPaint.measureText(mDisplayedValues[i]); 1300ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov if (textWidth > maxTextWidth) { 1301ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov maxTextWidth = (int) textWidth; 1302ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1303ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1304ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1305ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov maxTextWidth += mInputText.getPaddingLeft() + mInputText.getPaddingRight(); 1306ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov if (mMaxWidth != maxTextWidth) { 1307ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov if (maxTextWidth > mMinWidth) { 1308ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov mMaxWidth = maxTextWidth; 1309ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } else { 1310ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov mMaxWidth = mMinWidth; 1311ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1312ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov invalidate(); 1313ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1314ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov } 1315ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov 1316ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov /** 1317e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Gets whether the selector wheel wraps when reaching the min/max value. 131868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 1319e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return True if the selector wheel wraps. 13204bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 1321e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #getMinValue() 1322e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @see #getMaxValue() 132368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1324e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public boolean getWrapSelectorWheel() { 1325e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mWrapSelectorWheel; 1326206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1327206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1328206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1329e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets whether the selector wheel shown during flinging/scrolling should 1330e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * wrap around the {@link NumberPicker#getMinValue()} and 1331e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * {@link NumberPicker#getMaxValue()} values. 1332e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 1333d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * By default if the range (max - min) is more than the number of items shown 1334d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * on the selector wheel the selector wheel wrapping is enabled. 1335e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 13363f9c9eab7b41c409c3c7b503b89ad340e408b6a0Svetoslav Ganov * <p> 1337d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * <strong>Note:</strong> If the number of items, i.e. the range ( 1338d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * {@link #getMaxValue()} - {@link #getMinValue()}) is less than 1339d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * the number of items shown on the selector wheel, the selector wheel will 1340d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * not wrap. Hence, in such a case calling this method is a NOP. 13413f9c9eab7b41c409c3c7b503b89ad340e408b6a0Svetoslav Ganov * </p> 1342d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * 13436304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov * @param wrapSelectorWheel Whether to wrap. 1344206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 13456304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov public void setWrapSelectorWheel(boolean wrapSelectorWheel) { 13463f9c9eab7b41c409c3c7b503b89ad340e408b6a0Svetoslav Ganov final boolean wrappingAllowed = (mMaxValue - mMinValue) >= mSelectorIndices.length; 13473f9c9eab7b41c409c3c7b503b89ad340e408b6a0Svetoslav Ganov if ((!wrapSelectorWheel || wrappingAllowed) && wrapSelectorWheel != mWrapSelectorWheel) { 13486304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov mWrapSelectorWheel = wrapSelectorWheel; 1349206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13534bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * Sets the speed at which the numbers be incremented and decremented when 13544bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * the up and down buttons are long pressed respectively. 1355e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * <p> 1356e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * The default value is 300 ms. 1357e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * </p> 135868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 13594bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * @param intervalMillis The speed (in milliseconds) at which the numbers 1360e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * will be incremented and decremented. 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13624bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov public void setOnLongPressUpdateInterval(long intervalMillis) { 13634bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mLongPressUpdateInterval = intervalMillis; 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1365fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1366206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1367e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the value of the picker. 1368e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1369e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The value. 1370e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1371e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getValue() { 1372e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mValue; 1373e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1374e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1375e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1376e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the min value of the picker. 1377e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1378e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The min value 1379e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1380e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getMinValue() { 1381e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue; 1382e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1383e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1384e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1385e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the min value of the picker. 1386206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * 13877018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * @param minValue The min value inclusive. 13887018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * 13897018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * <strong>Note:</strong> The length of the displayed values array 13907018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * set via {@link #setDisplayedValues(String[])} must be equal to the 13917018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * range of selectable numbers which is equal to 13927018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * {@link #getMaxValue()} - {@link #getMinValue()} + 1. 1393206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1394e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setMinValue(int minValue) { 1395e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMinValue == minValue) { 1396e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1397e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1398e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (minValue < 0) { 1399e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov throw new IllegalArgumentException("minValue must be >= 0"); 1400e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1401e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMinValue = minValue; 1402e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMinValue > mValue) { 1403e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = mMinValue; 1404e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1405e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; 1406e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 1407b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov initializeSelectorWheelIndices(); 1408e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1409ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov tryComputeMaxWidth(); 1410d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov invalidate(); 1411206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1412206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 14134bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 1414e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Returns the max value of the picker. 14154bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 1416e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The max value. 14174bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 1418e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public int getMaxValue() { 1419e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMaxValue; 14204bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov } 14214bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov 14224bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov /** 1423e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the max value of the picker. 14244bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov * 14257018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * @param maxValue The max value inclusive. 14267018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * 14277018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * <strong>Note:</strong> The length of the displayed values array 14287018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * set via {@link #setDisplayedValues(String[])} must be equal to the 14297018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * range of selectable numbers which is equal to 14307018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * {@link #getMaxValue()} - {@link #getMinValue()} + 1. 14314bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov */ 1432e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setMaxValue(int maxValue) { 1433e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMaxValue == maxValue) { 1434e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1435e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1436e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (maxValue < 0) { 1437e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov throw new IllegalArgumentException("maxValue must be >= 0"); 1438e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1439e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mMaxValue = maxValue; 1440e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mMaxValue < mValue) { 1441e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mValue = mMaxValue; 1442e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1443e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; 1444e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov setWrapSelectorWheel(wrapSelectorWheel); 1445b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov initializeSelectorWheelIndices(); 1446e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1447ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov tryComputeMaxWidth(); 1448d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov invalidate(); 1449e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1450e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1451e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1452e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Gets the values to be displayed instead of string values. 1453e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1454e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @return The displayed values. 1455e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1456e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public String[] getDisplayedValues() { 1457e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mDisplayedValues; 1458e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1459e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov 1460e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov /** 1461e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * Sets the values to be displayed. 1462e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * 1463e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov * @param displayedValues The displayed values. 14647018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * 14657018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * <strong>Note:</strong> The length of the displayed values array 14667018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * must be equal to the range of selectable numbers which is equal to 14677018cfdc05dc6135949806749ff5c370dce09cedSvetoslav Ganov * {@link #getMaxValue()} - {@link #getMinValue()} + 1. 1468e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov */ 1469e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov public void setDisplayedValues(String[] displayedValues) { 1470e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mDisplayedValues == displayedValues) { 1471e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return; 1472e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1473e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mDisplayedValues = displayedValues; 1474e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mDisplayedValues != null) { 1475e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov // Allow text entry rather than strictly numeric entry. 1476e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT 1477e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); 1478e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } else { 1479e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 1480e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } 1481e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov updateInputTextView(); 1482b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov initializeSelectorWheelIndices(); 14839f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov tryComputeMaxWidth(); 1484206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1485206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1486206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1487206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getTopFadingEdgeStrength() { 1488206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 1489206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1490206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1491206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1492206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected float getBottomFadingEdgeStrength() { 1493206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; 1494206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1495206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1496206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1497206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDetachedFromWindow() { 149846bfc4811094e5b1e3196246e457d4c6b58332ecRomain Guy super.onDetachedFromWindow(); 1499206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeAllCallbacks(); 1500206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1501206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1502206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 1503206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected void onDraw(Canvas canvas) { 1504d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 1505d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov super.onDraw(canvas); 1506206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1507206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 15089eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout final boolean showSelectorWheel = mHideWheelUntilFocused ? hasFocus() : true; 1509206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float x = (mRight - mLeft) / 2; 1510206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov float y = mCurrentScrollOffset; 1511206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1512232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov // draw the virtual buttons pressed state if needed 15139eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout if (showSelectorWheel && mVirtualButtonPressedDrawable != null 1514232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov && mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { 1515232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (mDecrementVirtualButtonPressed) { 1516232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mVirtualButtonPressedDrawable.setState(PRESSED_STATE_SET); 1517232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mVirtualButtonPressedDrawable.setBounds(0, 0, mRight, mTopSelectionDividerTop); 1518232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mVirtualButtonPressedDrawable.draw(canvas); 1519232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 1520232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (mIncrementVirtualButtonPressed) { 1521232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mVirtualButtonPressedDrawable.setState(PRESSED_STATE_SET); 1522232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mVirtualButtonPressedDrawable.setBounds(0, mBottomSelectionDividerBottom, mRight, 1523232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mBottom); 1524232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mVirtualButtonPressedDrawable.draw(canvas); 1525232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 1526232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 1527232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 15289cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the selector wheel 1529b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov int[] selectorIndices = mSelectorIndices; 1530206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length; i++) { 1531206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int selectorIndex = selectorIndices[i]; 1532206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex); 1533d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // Do not draw the middle item if input is visible since the input 1534d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // is shown only if the wheel is static and it covers the middle 1535d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // item. Otherwise, if the user starts editing the text via the 1536d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // IME he may see a dimmed version of the old value intermixed 1537d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // with the new one. 15389eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout if ((showSelectorWheel && i != SELECTOR_MIDDLE_ITEM_INDEX) || 15399eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout (i == SELECTOR_MIDDLE_ITEM_INDEX && mInputText.getVisibility() != VISIBLE)) { 15406304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov canvas.drawText(scrollSelectorValue, x, y, mSelectorWheelPaint); 15416304b0d58e74509a9f21b67b5227b2fee2f1b60fSvetoslav Ganov } 1542206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov y += mSelectorElementHeight; 1543206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 15449cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 1545d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // draw the selection dividers 15469eef3f4fb92d4abd4e217c13cdf72bd4fc3e59f2Craig Stout if (showSelectorWheel && mSelectionDivider != null) { 15479cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the top divider 1548d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int topOfTopDivider = mTopSelectionDividerTop; 15499cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int bottomOfTopDivider = topOfTopDivider + mSelectionDividerHeight; 15509cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setBounds(0, topOfTopDivider, mRight, bottomOfTopDivider); 15519cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.draw(canvas); 15529cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 15539cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov // draw the bottom divider 1554d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int bottomOfBottomDivider = mBottomSelectionDividerBottom; 1555d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int topOfBottomDivider = bottomOfBottomDivider - mSelectionDividerHeight; 15569cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.setBounds(0, topOfBottomDivider, mRight, bottomOfBottomDivider); 15579cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mSelectionDivider.draw(canvas); 15589cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1560fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 15613fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov @Override 15628a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 15638a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityEvent(event); 15648a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov event.setClassName(NumberPicker.class.getName()); 1565d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov event.setScrollable(true); 1566d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov event.setScrollY((mMinValue + mValue) * mSelectorElementHeight); 1567d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov event.setMaxScrollY((mMaxValue - mMinValue) * mSelectorElementHeight); 15688a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 15698a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 15708a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 1571d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov public AccessibilityNodeProvider getAccessibilityNodeProvider() { 1572d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!mHasSelectorWheel) { 1573d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return super.getAccessibilityNodeProvider(); 1574d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1575d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mAccessibilityNodeProvider == null) { 1576d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mAccessibilityNodeProvider = new AccessibilityNodeProviderImpl(); 1577d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1578d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return mAccessibilityNodeProvider; 15798a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 15808a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 158168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1582ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov * Makes a measure spec that tries greedily to use the max value. 1583e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov * 1584e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov * @param measureSpec The measure spec. 1585698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov * @param maxSize The max value for the size. 1586ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov * @return A measure spec greedily imposing the max size. 1587e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov */ 1588698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov private int makeMeasureSpec(int measureSpec, int maxSize) { 15899f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov if (maxSize == SIZE_UNSPECIFIED) { 15909f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov return measureSpec; 15919f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov } 1592ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov final int size = MeasureSpec.getSize(measureSpec); 1593e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov final int mode = MeasureSpec.getMode(measureSpec); 1594e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov switch (mode) { 1595e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov case MeasureSpec.EXACTLY: 1596ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov return measureSpec; 1597e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov case MeasureSpec.AT_MOST: 1598698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov return MeasureSpec.makeMeasureSpec(Math.min(size, maxSize), MeasureSpec.EXACTLY); 1599e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov case MeasureSpec.UNSPECIFIED: 1600698e1d5d867a7ac653fa1d6f29cef4cfb73fad38Svetoslav Ganov return MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.EXACTLY); 1601e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov default: 1602ec1e06a00d26a783fb948e739ad8157c03e55302Svetoslav Ganov throw new IllegalArgumentException("Unknown measure mode: " + mode); 1603e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov } 1604e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov } 1605e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov 1606e0c8ab5aaa02d7b9b01fe68fb893af4d78482f6cSvetoslav Ganov /** 1607d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Utility to reconcile a desired size and state, with constraints imposed 1608d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * by a MeasureSpec. Tries to respect the min size, unless a different size 1609d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * is imposed by the constraints. 16109f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov * 16119f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov * @param minSize The minimal desired size. 16129f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov * @param measuredSize The currently measured size. 16139f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov * @param measureSpec The current measure spec. 16149f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov * @return The resolved size and state. 16159f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov */ 1616d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private int resolveSizeAndStateRespectingMinSize( 1617d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int minSize, int measuredSize, int measureSpec) { 16189f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov if (minSize != SIZE_UNSPECIFIED) { 16199f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov final int desiredWidth = Math.max(minSize, measuredSize); 16209f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov return resolveSizeAndState(desiredWidth, measureSpec, 0); 16219f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov } else { 16229f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov return measuredSize; 16239f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov } 16249f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov } 16259f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov 16269f086d812ff04703de4b14e02a7702ba7c8acb33Svetoslav Ganov /** 1627d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Resets the selector indices and clear the cached string representation of 1628d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * these indices. 1629a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov */ 1630b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private void initializeSelectorWheelIndices() { 1631a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov mSelectorIndexToStringCache.clear(); 1632232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov int[] selectorIndices = mSelectorIndices; 1633b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov int current = getValue(); 1634b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov for (int i = 0; i < mSelectorIndices.length; i++) { 1635b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX); 1636b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov if (mWrapSelectorWheel) { 1637b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov selectorIndex = getWrappedSelectorIndex(selectorIndex); 1638b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } 1639232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov selectorIndices[i] = selectorIndex; 1640232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov ensureCachedScrollSelectorValue(selectorIndices[i]); 1641a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1642a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov } 1643a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov 1644a911d4a2b1be7e9ea909a579167826e4a5bac1a3Svetoslav Ganov /** 1645d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Sets the current value of this NumberPicker. 164668f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook * 1647d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * @param current The new value of the NumberPicker. 1648d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * @param notifyChange Whether to notify if the current value changed. 164968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1650d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void setValueInternal(int current, boolean notifyChange) { 1651e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mValue == current) { 1652206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1653206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wrap around the values if we go past the start or end 1655e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel) { 1656206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov current = getWrappedSelectorIndex(current); 1657d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 1658d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov current = Math.max(current, mMinValue); 1659d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov current = Math.min(current, mMaxValue); 16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1661e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int previous = mValue; 1662d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mValue = current; 1663d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov updateInputTextView(); 1664d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (notifyChange) { 1665d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov notifyChange(previous, current); 1666d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1667fac14f9731ce7fc765de582c983af751aab697deSvetoslav Ganov initializeSelectorWheelIndices(); 1668fac14f9731ce7fc765de582c983af751aab697deSvetoslav Ganov invalidate(); 16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1670fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 167168f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1672b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * Changes the current value by one which is increment or 1673b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * decrement based on the passes argument. 1674d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * decrement the current value. 1675b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * 1676b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * @param increment True to increment, false to decrement. 1677b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov */ 1678d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void changeValueByOne(boolean increment) { 1679d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mHasSelectorWheel) { 1680b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov mInputText.setVisibility(View.INVISIBLE); 1681d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!moveToFinalScrollerPosition(mFlingScroller)) { 1682d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov moveToFinalScrollerPosition(mAdjustScroller); 1683d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1684b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov mPreviousScrollerY = 0; 1685b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov if (increment) { 1686fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov mFlingScroller.startScroll(0, 0, 0, -mSelectorElementHeight, SNAP_SCROLL_DURATION); 1687b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } else { 1688fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov mFlingScroller.startScroll(0, 0, 0, mSelectorElementHeight, SNAP_SCROLL_DURATION); 1689b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } 1690b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov invalidate(); 1691b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } else { 1692b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov if (increment) { 1693d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov setValueInternal(mValue + 1, true); 1694b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } else { 1695d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov setValueInternal(mValue - 1, true); 1696b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } 1697b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } 1698b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } 1699b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov 1700b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private void initializeSelectorWheel() { 1701b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov initializeSelectorWheelIndices(); 1702b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov int[] selectorIndices = mSelectorIndices; 17039cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov int totalTextHeight = selectorIndices.length * mTextSize; 170401fa0d7aae1a551e1e7cfb90d2aeaf2fcb3978afSvetoslav Ganov float totalTextGapHeight = (mBottom - mTop) - totalTextHeight; 1705d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov float textGapCount = selectorIndices.length; 1706b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov mSelectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f); 1707b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov mSelectorElementHeight = mTextSize + mSelectorTextGapHeight; 1708d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // Ensure that the middle item is positioned the same as the text in 1709d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // mInputText 1710eeafd4296b7cf4c2ad9c985562f6d70e2a3ffc03Chet Haase int editTextTextPosition = mInputText.getBaseline() + mInputText.getTop(); 1711d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mInitialScrollOffset = editTextTextPosition 1712d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov - (mSelectorElementHeight * SELECTOR_MIDDLE_ITEM_INDEX); 17136a19fcde07527706c2a9175e0b9f2a71549b7ffeSvetoslav Ganov mCurrentScrollOffset = mInitialScrollOffset; 17149cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov updateInputTextView(); 17159cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 17169cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov 1717b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private void initializeFadingEdges() { 1718b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov setVerticalFadingEdgeEnabled(true); 1719b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov setFadingEdgeLength((mBottom - mTop - mTextSize) / 2); 1720b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } 1721b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov 1722206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1723206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Callback invoked upon completion of a given <code>scroller</code>. 1724206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1725206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void onScrollerFinished(Scroller scroller) { 1726206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scroller == mFlingScroller) { 1727d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!ensureScrollWheelAdjusted()) { 1728b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov updateInputTextView(); 1729b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov } 1730d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); 17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1732d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 1733d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov updateInputTextView(); 1734d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1737fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1738206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 17399cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * Handles transition to a given <code>scrollState</code> 174050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov */ 17419cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov private void onScrollStateChange(int scrollState) { 17429cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mScrollState == scrollState) { 17439cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov return; 17449cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov } 17459cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov mScrollState = scrollState; 17469cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov if (mOnScrollListener != null) { 17474bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov mOnScrollListener.onScrollStateChange(this, scrollState); 174850f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 174950f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov } 175050f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov 175150f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov /** 1752206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Flings the selector with the given <code>velocityY</code>. 1753206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1754206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void fling(int velocityY) { 1755206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mPreviousScrollerY = 0; 1756206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1757234484a9fb53786aa8b7ed2a3df7e24d41817689Svetoslav Ganov if (velocityY > 0) { 1758234484a9fb53786aa8b7ed2a3df7e24d41817689Svetoslav Ganov mFlingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 1759206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1760234484a9fb53786aa8b7ed2a3df7e24d41817689Svetoslav Ganov mFlingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); 17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1762206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 1763206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov invalidate(); 17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1766206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1767206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The wrapped index <code>selectorIndex</code> value. 176868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 1769206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getWrappedSelectorIndex(int selectorIndex) { 1770e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndex > mMaxValue) { 1771e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1; 1772e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov } else if (selectorIndex < mMinValue) { 1773e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1; 1774206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1775206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return selectorIndex; 17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1777fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1778206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1779206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Increments the <code>selectorIndices</code> whose string representations 1780206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1781206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1782b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private void incrementSelectorIndices(int[] selectorIndices) { 1783206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = 0; i < selectorIndices.length - 1; i++) { 1784206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i + 1]; 1785206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1786206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[selectorIndices.length - 2] + 1; 1787e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel && nextScrollSelectorIndex > mMaxValue) { 1788e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov nextScrollSelectorIndex = mMinValue; 1789206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1790206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[selectorIndices.length - 1] = nextScrollSelectorIndex; 1791206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1792206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1793fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1794206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1795206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Decrements the <code>selectorIndices</code> whose string representations 1796206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * will be displayed in the selector. 1797206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1798206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void decrementSelectorIndices(int[] selectorIndices) { 1799206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (int i = selectorIndices.length - 1; i > 0; i--) { 1800206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[i] = selectorIndices[i - 1]; 1801206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1802206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int nextScrollSelectorIndex = selectorIndices[1] - 1; 1803e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (mWrapSelectorWheel && nextScrollSelectorIndex < mMinValue) { 1804e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov nextScrollSelectorIndex = mMaxValue; 1805206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1806206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov selectorIndices[0] = nextScrollSelectorIndex; 1807206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov ensureCachedScrollSelectorValue(nextScrollSelectorIndex); 1808206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1809fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1810206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1811206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensures we have a cached string representation of the given <code> 1812d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * selectorIndex</code> to avoid multiple instantiations of the same string. 1813206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1814206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void ensureCachedScrollSelectorValue(int selectorIndex) { 1815206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov SparseArray<String> cache = mSelectorIndexToStringCache; 1816206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String scrollSelectorValue = cache.get(selectorIndex); 1817206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (scrollSelectorValue != null) { 1818206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return; 1819206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1820e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov if (selectorIndex < mMinValue || selectorIndex > mMaxValue) { 1821206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = ""; 1822206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1823206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues != null) { 1824e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov int displayedValueIndex = selectorIndex - mMinValue; 182550f34d14f6dd3411fdbdb6a7b8b285c2b8fdbf5cSvetoslav Ganov scrollSelectorValue = mDisplayedValues[displayedValueIndex]; 1826206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1827206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov scrollSelectorValue = formatNumber(selectorIndex); 18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1830206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov cache.put(selectorIndex, scrollSelectorValue); 18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1832fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1833206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private String formatNumber(int value) { 1834d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio return (mFormatter != null) ? mFormatter.format(value) : formatNumberWithLocale(value); 1835206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1837206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void validateInputTextView(View v) { 1838206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(((TextView) v).getText()); 1839206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(str)) { 1840206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Restore to the old value as we don't allow empty values 1841206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov updateInputTextView(); 1842206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1843206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Check the new value and ensure it's in range 1844206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int current = getSelectedPos(str.toString()); 1845d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov setValueInternal(current, true); 18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1847206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1848fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1849206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1850206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Updates the view of this NumberPicker. If displayValues were specified in 18519cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * the string corresponding to the index specified by the current value will 18529cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * be returned. Otherwise, the formatter specified in {@link #setFormatter} 18539cd5fb2f46e219ec8250383fb201b94cb2ee8c0aSvetoslav Ganov * will be used to format the number. 1854d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * 1855d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * @return Whether the text was updated. 1856206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1857d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private boolean updateInputTextView() { 1858206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1859206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * If we don't have displayed values then use the current number else 1860206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * find the correct value in the displayed values for the current 1861206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * number. 1862206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1863d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov String text = (mDisplayedValues == null) ? formatNumber(mValue) 1864d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov : mDisplayedValues[mValue - mMinValue]; 1865d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!TextUtils.isEmpty(text) && !text.equals(mInputText.getText().toString())) { 1866d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mInputText.setText(text); 1867d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return true; 18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18693fec3fe0e3a83c5e0d1264f34bcc55b158537bc6Svetoslav Ganov 1870d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return false; 1871206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1872fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1873206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1874206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Notifies the listener, if registered, of a change of the value of this 1875206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * NumberPicker. 1876206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1877206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void notifyChange(int previous, int current) { 1878cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov if (mOnValueChangeListener != null) { 1879cedc446684e94c9971c38c3206f1f224314bda2aSvetoslav Ganov mOnValueChangeListener.onValueChange(this, previous, mValue); 1880206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1881206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1883206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1884b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * Posts a command for changing the current value by one. 1885b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * 1886b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * @param increment Whether to increment or decrement the value. 1887206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1888d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void postChangeCurrentByOneFromLongPress(boolean increment, long delayMillis) { 1889b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov if (mChangeCurrentByOneFromLongPressCommand == null) { 1890b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov mChangeCurrentByOneFromLongPressCommand = new ChangeCurrentByOneFromLongPressCommand(); 1891d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 1892d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeCallbacks(mChangeCurrentByOneFromLongPressCommand); 1893d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1894d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mChangeCurrentByOneFromLongPressCommand.setStep(increment); 1895d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov postDelayed(mChangeCurrentByOneFromLongPressCommand, delayMillis); 1896d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1897d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 1898d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 1899d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Removes the command for changing the current value by one. 1900d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 1901d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void removeChangeCurrentByOneFromLongPress() { 1902d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mChangeCurrentByOneFromLongPressCommand != null) { 1903d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeCallbacks(mChangeCurrentByOneFromLongPressCommand); 1904d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1905d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1906d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 1907d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 1908d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Posts a command for beginning an edit of the current value via IME on 1909d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * long press. 1910d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 1911d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void postBeginSoftInputOnLongPressCommand() { 1912d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mBeginSoftInputOnLongPressCommand == null) { 1913d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mBeginSoftInputOnLongPressCommand = new BeginSoftInputOnLongPressCommand(); 1914d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } else { 1915d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeCallbacks(mBeginSoftInputOnLongPressCommand); 1916d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1917d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov postDelayed(mBeginSoftInputOnLongPressCommand, ViewConfiguration.getLongPressTimeout()); 1918d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1919d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 1920d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 1921d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Removes the command for beginning an edit of the current value via IME. 1922d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 1923d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void removeBeginSoftInputCommand() { 1924d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mBeginSoftInputOnLongPressCommand != null) { 1925d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeCallbacks(mBeginSoftInputOnLongPressCommand); 1926206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1927206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1930206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Removes all pending callback from the message queue. 1931206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1932206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void removeAllCallbacks() { 1933b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov if (mChangeCurrentByOneFromLongPressCommand != null) { 1934b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov removeCallbacks(mChangeCurrentByOneFromLongPressCommand); 1935206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1936206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand != null) { 1937206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1939d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mBeginSoftInputOnLongPressCommand != null) { 1940d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov removeCallbacks(mBeginSoftInputOnLongPressCommand); 1941d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 1942232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mPressedStateHelper.cancel(); 19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1945206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 1946206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * @return The selected index given its displayed <code>value</code>. 1947206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 1948206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int getSelectedPos(String value) { 19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisplayedValues == null) { 1950aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy try { 1951206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 1952aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } catch (NumberFormatException e) { 1953206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 1954aa516beb79693ceffbd81a7c9d14c940e412cccbRomain Guy } 19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mDisplayedValues.length; i++) { 1957206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Don't force the user to type in jan when ja will do 1958206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov value = value.toLowerCase(); 1959206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues[i].toLowerCase().startsWith(value)) { 1960e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue + i; 19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1963fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1964206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 1965206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * The user might have typed in a number into the month field i.e. 19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10 instead of OCT so support that too. 19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 1969206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return Integer.parseInt(value); 19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 1971fdf6db6748b32f620a7f68b13a67c38b4e59e5edTom Taylor 1972206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // Ignore as if it's not a number we don't care 19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1975e9730bf3d2dcbea1879f24c18aaf9810ac57084cSvetoslav Ganov return mMinValue; 19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1979206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Posts an {@link SetSelectionCommand} from the given <code>selectionStart 1980d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * </code> to <code>selectionEnd</code>. 19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1982206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private void postSetSelectionCommand(int selectionStart, int selectionEnd) { 1983206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mSetSelectionCommand == null) { 1984206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand = new SetSelectionCommand(); 1985206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 1986206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov removeCallbacks(mSetSelectionCommand); 1987206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 1988206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionStart = selectionStart; 1989206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mSetSelectionCommand.mSelectionEnd = selectionEnd; 1990206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov post(mSetSelectionCommand); 19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 199268f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook 199368f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook /** 1994d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio * The numbers accepted by the input text's {@link Filter} 1995d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio */ 1996d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio private static final char[] DIGIT_CHARACTERS = new char[] { 1997d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio // Latin digits are the common case 1998d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 1999d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio // Arabic-Indic 2000d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio '\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668' 2001d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio , '\u0669', 2002d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio // Extended Arabic-Indic 2003d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8' 2004962dde734b7e347948a1624571e8c180260bae85Martin Olsson , '\u06f9', 2005962dde734b7e347948a1624571e8c180260bae85Martin Olsson // Hindi and Marathi (Devanagari script) 2006962dde734b7e347948a1624571e8c180260bae85Martin Olsson '\u0966', '\u0967', '\u0968', '\u0969', '\u096a', '\u096b', '\u096c', '\u096d', '\u096e' 2007962dde734b7e347948a1624571e8c180260bae85Martin Olsson , '\u096f', 2008962dde734b7e347948a1624571e8c180260bae85Martin Olsson // Bengali 2009962dde734b7e347948a1624571e8c180260bae85Martin Olsson '\u09e6', '\u09e7', '\u09e8', '\u09e9', '\u09ea', '\u09eb', '\u09ec', '\u09ed', '\u09ee' 2010962dde734b7e347948a1624571e8c180260bae85Martin Olsson , '\u09ef', 2011962dde734b7e347948a1624571e8c180260bae85Martin Olsson // Kannada 2012962dde734b7e347948a1624571e8c180260bae85Martin Olsson '\u0ce6', '\u0ce7', '\u0ce8', '\u0ce9', '\u0cea', '\u0ceb', '\u0cec', '\u0ced', '\u0cee' 2013962dde734b7e347948a1624571e8c180260bae85Martin Olsson , '\u0cef' 2014d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio }; 2015d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 2016d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio /** 2017206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Filter for accepting only valid indices or prefixes of the string 2018206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * representation of valid indices. 201968f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook */ 2020206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class InputTextFilter extends NumberKeyListener { 2021206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2022206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // XXX This doesn't allow for range limits when controlled by a 2023206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov // soft input method! 2024206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public int getInputType() { 2025206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return InputType.TYPE_CLASS_TEXT; 2026206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2027206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2028206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 2029206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov protected char[] getAcceptedChars() { 2030206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return DIGIT_CHARACTERS; 2031206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2032206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2033206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov @Override 2034d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov public CharSequence filter( 2035d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { 2036206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (mDisplayedValues == null) { 2037206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = super.filter(source, start, end, dest, dstart, dend); 2038206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (filtered == null) { 2039206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov filtered = source.subSequence(start, end); 2040206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2041206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2042206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 2043206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 2044206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2045206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if ("".equals(result)) { 2046206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return result; 2047206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2048206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov int val = getSelectedPos(result); 2049206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2050206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /* 2051206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Ensure the user can't type in a value greater than the max 2052206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * allowed. We have to allow less than min as the user might 2053206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * want to delete some numbers and then type a new number. 20546d8a99fecc5dd3aec502c0419af61e8d2a3c398dSungmin Choi * And prevent multiple-"0" that exceeds the length of upper 20556d8a99fecc5dd3aec502c0419af61e8d2a3c398dSungmin Choi * bound number. 2056206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 20576d8a99fecc5dd3aec502c0419af61e8d2a3c398dSungmin Choi if (val > mMaxValue || result.length() > String.valueOf(mMaxValue).length()) { 2058206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 2059206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 2060206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return filtered; 2061206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2062206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } else { 2063206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov CharSequence filtered = String.valueOf(source.subSequence(start, end)); 2064206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (TextUtils.isEmpty(filtered)) { 2065206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 2066206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2067206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String result = String.valueOf(dest.subSequence(0, dstart)) + filtered 2068206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov + dest.subSequence(dend, dest.length()); 2069206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String str = String.valueOf(result).toLowerCase(); 2070206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov for (String val : mDisplayedValues) { 2071206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov String valLowerCase = val.toLowerCase(); 2072206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov if (valLowerCase.startsWith(str)) { 2073206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov postSetSelectionCommand(result.length(), val.length()); 2074206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return val.subSequence(dstart, val.length()); 2075206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2076206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2077206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov return ""; 2078206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2079206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2080206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2081206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2082206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 2083d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Ensures that the scroll wheel is adjusted i.e. there is no offset and the 2084d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * middle element is in the middle of the widget. 2085d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * 2086d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * @return Whether an adjustment has been made. 2087d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 2088d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private boolean ensureScrollWheelAdjusted() { 2089d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov // adjust to the closest value 2090d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int deltaY = mInitialScrollOffset - mCurrentScrollOffset; 2091d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (deltaY != 0) { 2092d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mPreviousScrollerY = 0; 2093d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (Math.abs(deltaY) > mSelectorElementHeight / 2) { 2094d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov deltaY += (deltaY > 0) ? -mSelectorElementHeight : mSelectorElementHeight; 2095d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2096d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mAdjustScroller.startScroll(0, 0, 0, deltaY, SELECTOR_ADJUSTMENT_DURATION_MILLIS); 2097d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov invalidate(); 2098d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return true; 2099d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2100d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return false; 2101d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2102d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2103232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov class PressedStateHelper implements Runnable { 2104232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov public static final int BUTTON_INCREMENT = 1; 2105232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov public static final int BUTTON_DECREMENT = 2; 2106232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 2107232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov private final int MODE_PRESS = 1; 2108232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov private final int MODE_TAPPED = 2; 2109232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 2110232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov private int mManagedButton; 2111232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov private int mMode; 2112232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 2113232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov public void cancel() { 2114232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mMode = 0; 2115232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mManagedButton = 0; 2116232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov NumberPicker.this.removeCallbacks(this); 2117232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (mIncrementVirtualButtonPressed) { 2118232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mIncrementVirtualButtonPressed = false; 2119232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); 2120232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2121232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mDecrementVirtualButtonPressed = false; 2122232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (mDecrementVirtualButtonPressed) { 2123232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov invalidate(0, 0, mRight, mTopSelectionDividerTop); 2124fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov } 2125fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov } 2126fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov 2127232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov public void buttonPressDelayed(int button) { 2128232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov cancel(); 2129232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mMode = MODE_PRESS; 2130232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mManagedButton = button; 2131232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov NumberPicker.this.postDelayed(this, ViewConfiguration.getTapTimeout()); 2132232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2133232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 2134232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov public void buttonTapped(int button) { 2135232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov cancel(); 2136232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mMode = MODE_TAPPED; 2137232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mManagedButton = button; 2138232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov NumberPicker.this.post(this); 2139232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2140232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov 2141232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov @Override 2142232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov public void run() { 2143232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov switch (mMode) { 2144232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov case MODE_PRESS: { 2145232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov switch (mManagedButton) { 2146232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov case BUTTON_INCREMENT: { 2147232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mIncrementVirtualButtonPressed = true; 2148232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); 2149232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } break; 2150232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov case BUTTON_DECREMENT: { 2151232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mDecrementVirtualButtonPressed = true; 2152232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov invalidate(0, 0, mRight, mTopSelectionDividerTop); 2153232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2154232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2155232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } break; 2156232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov case MODE_TAPPED: { 2157232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov switch (mManagedButton) { 2158232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov case BUTTON_INCREMENT: { 2159232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (!mIncrementVirtualButtonPressed) { 2160232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov NumberPicker.this.postDelayed(this, 2161232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov ViewConfiguration.getPressedStateDuration()); 2162232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2163232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mIncrementVirtualButtonPressed ^= true; 2164232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); 2165232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } break; 2166232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov case BUTTON_DECREMENT: { 2167232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov if (!mDecrementVirtualButtonPressed) { 2168232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov NumberPicker.this.postDelayed(this, 2169232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov ViewConfiguration.getPressedStateDuration()); 2170232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2171232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov mDecrementVirtualButtonPressed ^= true; 2172232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov invalidate(0, 0, mRight, mTopSelectionDividerTop); 2173232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2174232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } 2175232dd3f335b8995cd9ab220f7b3fad77076de42bSvetoslav Ganov } break; 2176fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov } 2177fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov } 2178fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov } 2179fe41ce4ef97e7da585fdbf06988da8047e72b9f6Svetoslav Ganov 2180d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 2181206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov * Command for setting the input text selection. 2182206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 2183206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov class SetSelectionCommand implements Runnable { 2184206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionStart; 2185206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2186206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov private int mSelectionEnd; 2187206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2188206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 2189206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov mInputText.setSelection(mSelectionStart, mSelectionEnd); 2190206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2191206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2192206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2193206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov /** 2194b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov * Command for changing the current value from a long press by one. 2195206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov */ 2196b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov class ChangeCurrentByOneFromLongPressCommand implements Runnable { 2197b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov private boolean mIncrement; 2198206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2199d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void setStep(boolean increment) { 2200b80a3fcad1776c1b9abe3662899660b4f88ac2abSvetoslav Ganov mIncrement = increment; 2201206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 2202206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov 2203d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov @Override 2204206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov public void run() { 2205d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov changeValueByOne(mIncrement); 22064bfd794475e6fb34c9dfa83d4302e9db365a3709Svetoslav Ganov postDelayed(this, mLongPressUpdateInterval); 2207206316a61f904ea0a6b106137dd7715a2c246d4cSvetoslav Ganov } 220868f2f547f56f239b60d13b2b62a08a65874f6662Paul Westbrook } 2209a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov 2210a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov /** 2211a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov * @hide 2212a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov */ 2213a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov public static class CustomEditText extends EditText { 2214a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov 2215a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov public CustomEditText(Context context, AttributeSet attrs) { 2216a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov super(context, attrs); 2217a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov } 2218a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov 2219a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov @Override 2220a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov public void onEditorAction(int actionCode) { 2221a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov super.onEditorAction(actionCode); 2222a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov if (actionCode == EditorInfo.IME_ACTION_DONE) { 2223a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov clearFocus(); 2224a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov } 2225a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov } 2226a2b41b438d45570867e4682c0caaf93ace5e712eSvetoslav Ganov } 2227d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2228d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov /** 2229d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov * Command for beginning soft input on long press. 2230d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov */ 2231d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov class BeginSoftInputOnLongPressCommand implements Runnable { 2232d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2233d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov @Override 2234d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov public void run() { 223546a27efe9528ac3c5b37726707844e7c868815acSvetoslav performLongClick(); 2236d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2237d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2238d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2239791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov /** 2240791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov * Class for managing virtual view tree rooted at this picker. 2241791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov */ 2242d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov class AccessibilityNodeProviderImpl extends AccessibilityNodeProvider { 2243791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov private static final int UNDEFINED = Integer.MIN_VALUE; 2244791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2245d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private static final int VIRTUAL_VIEW_ID_INCREMENT = 1; 2246d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2247d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private static final int VIRTUAL_VIEW_ID_INPUT = 2; 2248d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2249d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private static final int VIRTUAL_VIEW_ID_DECREMENT = 3; 2250d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2251d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private final Rect mTempRect = new Rect(); 2252d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2253d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private final int[] mTempArray = new int[2]; 2254d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2255791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov private int mAccessibilityFocusedView = UNDEFINED; 2256791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2257d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov @Override 2258d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { 2259d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (virtualViewId) { 2260d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case View.NO_ID: 2261d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return createAccessibilityNodeInfoForNumberPicker( mScrollX, mScrollY, 2262d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mScrollX + (mRight - mLeft), mScrollY + (mBottom - mTop)); 2263d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_DECREMENT: 2264d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return createAccessibilityNodeInfoForVirtualButton(VIRTUAL_VIEW_ID_DECREMENT, 2265d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov getVirtualDecrementButtonText(), mScrollX, mScrollY, 2266d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mScrollX + (mRight - mLeft), 2267d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mTopSelectionDividerTop + mSelectionDividerHeight); 2268d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INPUT: 22690e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette return createAccessibiltyNodeInfoForInputText(mScrollX, 22700e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette mTopSelectionDividerTop + mSelectionDividerHeight, 22710e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette mScrollX + (mRight - mLeft), 22720e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette mBottomSelectionDividerBottom - mSelectionDividerHeight); 2273d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INCREMENT: 2274d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return createAccessibilityNodeInfoForVirtualButton(VIRTUAL_VIEW_ID_INCREMENT, 2275d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov getVirtualIncrementButtonText(), mScrollX, 2276d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mBottomSelectionDividerBottom - mSelectionDividerHeight, 2277d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mScrollX + (mRight - mLeft), mScrollY + (mBottom - mTop)); 2278d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2279d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return super.createAccessibilityNodeInfo(virtualViewId); 2280d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2281d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2282d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov @Override 2283d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String searched, 2284d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int virtualViewId) { 2285d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (TextUtils.isEmpty(searched)) { 2286d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return Collections.emptyList(); 2287d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2288d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov String searchedLowerCase = searched.toLowerCase(); 2289d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov List<AccessibilityNodeInfo> result = new ArrayList<AccessibilityNodeInfo>(); 2290d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (virtualViewId) { 2291d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case View.NO_ID: { 2292d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov findAccessibilityNodeInfosByTextInChild(searchedLowerCase, 2293d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov VIRTUAL_VIEW_ID_DECREMENT, result); 2294d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov findAccessibilityNodeInfosByTextInChild(searchedLowerCase, 2295d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov VIRTUAL_VIEW_ID_INPUT, result); 2296d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov findAccessibilityNodeInfosByTextInChild(searchedLowerCase, 2297d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov VIRTUAL_VIEW_ID_INCREMENT, result); 2298d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return result; 2299d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2300d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_DECREMENT: 2301d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INCREMENT: 2302d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INPUT: { 2303d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov findAccessibilityNodeInfosByTextInChild(searchedLowerCase, virtualViewId, 2304d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov result); 2305d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return result; 2306d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2307d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2308d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return super.findAccessibilityNodeInfosByText(searched, virtualViewId); 2309d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2310d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2311d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov @Override 2312aa780c110922148a6a4ba06734bb2b0bb8c98f93Svetoslav Ganov public boolean performAction(int virtualViewId, int action, Bundle arguments) { 2313d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (virtualViewId) { 2314791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case View.NO_ID: { 2315791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov switch (action) { 2316791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 2317791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView != virtualViewId) { 2318791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mAccessibilityFocusedView = virtualViewId; 2319791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov requestAccessibilityFocus(); 2320791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return true; 2321791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2322791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2323791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 2324791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView == virtualViewId) { 2325791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mAccessibilityFocusedView = UNDEFINED; 2326791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov clearAccessibilityFocus(); 2327791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return true; 2328791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2329791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return false; 2330791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 233148d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { 2332fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled() 2333fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov && (getWrapSelectorWheel() || getValue() < getMaxValue())) { 233448d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov changeValueByOne(true); 233548d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov return true; 233648d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov } 233748d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov } return false; 233848d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { 2339fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled() 2340fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov && (getWrapSelectorWheel() || getValue() > getMinValue())) { 234148d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov changeValueByOne(false); 234248d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov return true; 234348d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov } 234448d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov } return false; 2345791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2346791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } break; 2347d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INPUT: { 2348d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (action) { 2349d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case AccessibilityNodeInfo.ACTION_FOCUS: { 2350fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled() && !mInputText.isFocused()) { 2351d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return mInputText.requestFocus(); 2352d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2353d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 2354d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: { 2355fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled() && mInputText.isFocused()) { 2356d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov mInputText.clearFocus(); 2357d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return true; 2358d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2359791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return false; 2360791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2361791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_CLICK: { 2362fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled()) { 236346a27efe9528ac3c5b37726707844e7c868815acSvetoslav performClick(); 236446a27efe9528ac3c5b37726707844e7c868815acSvetoslav return true; 236546a27efe9528ac3c5b37726707844e7c868815acSvetoslav } 236646a27efe9528ac3c5b37726707844e7c868815acSvetoslav return false; 236746a27efe9528ac3c5b37726707844e7c868815acSvetoslav } 236846a27efe9528ac3c5b37726707844e7c868815acSvetoslav case AccessibilityNodeInfo.ACTION_LONG_CLICK: { 236946a27efe9528ac3c5b37726707844e7c868815acSvetoslav if (NumberPicker.this.isEnabled()) { 237046a27efe9528ac3c5b37726707844e7c868815acSvetoslav performLongClick(); 2371fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov return true; 2372fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov } 2373fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov return false; 2374791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2375791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 2376791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView != virtualViewId) { 2377791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mAccessibilityFocusedView = virtualViewId; 2378791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov sendAccessibilityEventForVirtualView(virtualViewId, 2379791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 2380791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mInputText.invalidate(); 2381791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return true; 2382791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2383791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2384791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 2385791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView == virtualViewId) { 2386791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mAccessibilityFocusedView = UNDEFINED; 2387791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov sendAccessibilityEventForVirtualView(virtualViewId, 2388791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 2389791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mInputText.invalidate(); 2390791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return true; 2391791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2392791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2393791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov default: { 2394791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return mInputText.performAccessibilityAction(action, arguments); 2395791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2396d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2397791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2398791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case VIRTUAL_VIEW_ID_INCREMENT: { 2399791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov switch (action) { 2400791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_CLICK: { 2401fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled()) { 2402fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov NumberPicker.this.changeValueByOne(true); 2403fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov sendAccessibilityEventForVirtualView(virtualViewId, 2404fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_CLICKED); 2405fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov return true; 2406fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov } 2407fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov } return false; 2408791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 2409791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView != virtualViewId) { 2410791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mAccessibilityFocusedView = virtualViewId; 2411791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov sendAccessibilityEventForVirtualView(virtualViewId, 2412791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 2413791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); 2414791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return true; 2415791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2416791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2417791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 2418791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView == virtualViewId) { 2419791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mAccessibilityFocusedView = UNDEFINED; 2420791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov sendAccessibilityEventForVirtualView(virtualViewId, 2421791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 2422791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); 2423791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return true; 2424791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2425791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2426791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2427791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2428791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case VIRTUAL_VIEW_ID_DECREMENT: { 2429791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov switch (action) { 2430791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_CLICK: { 2431fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled()) { 2432fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov final boolean increment = (virtualViewId == VIRTUAL_VIEW_ID_INCREMENT); 2433fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov NumberPicker.this.changeValueByOne(increment); 2434fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov sendAccessibilityEventForVirtualView(virtualViewId, 2435fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_CLICKED); 2436fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov return true; 2437fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov } 2438fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov } return false; 2439791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 2440791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView != virtualViewId) { 2441791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mAccessibilityFocusedView = virtualViewId; 2442791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov sendAccessibilityEventForVirtualView(virtualViewId, 2443791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 2444791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov invalidate(0, 0, mRight, mTopSelectionDividerTop); 2445791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return true; 2446791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2447791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2448791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 2449791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView == virtualViewId) { 2450791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov mAccessibilityFocusedView = UNDEFINED; 2451791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov sendAccessibilityEventForVirtualView(virtualViewId, 2452791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 2453791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov invalidate(0, 0, mRight, mTopSelectionDividerTop); 2454791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return true; 2455791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2456791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2457791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2458791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } return false; 2459d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2460aa780c110922148a6a4ba06734bb2b0bb8c98f93Svetoslav Ganov return super.performAction(virtualViewId, action, arguments); 2461d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2462d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2463d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) { 2464d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (virtualViewId) { 2465d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_DECREMENT: { 2466791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (hasVirtualDecrementButton()) { 2467791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov sendAccessibilityEventForVirtualButton(virtualViewId, eventType, 2468791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov getVirtualDecrementButtonText()); 2469791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2470d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 2471d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INPUT: { 2472d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov sendAccessibilityEventForVirtualText(eventType); 2473d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 2474d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INCREMENT: { 2475791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (hasVirtualIncrementButton()) { 2476791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov sendAccessibilityEventForVirtualButton(virtualViewId, eventType, 2477791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov getVirtualIncrementButtonText()); 2478791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2479d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 2480d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2481d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2482d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2483d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void sendAccessibilityEventForVirtualText(int eventType) { 2484a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov if (AccessibilityManager.getInstance(mContext).isEnabled()) { 2485a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov AccessibilityEvent event = AccessibilityEvent.obtain(eventType); 2486a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov mInputText.onInitializeAccessibilityEvent(event); 2487a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov mInputText.onPopulateAccessibilityEvent(event); 2488a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov event.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT); 2489a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov requestSendAccessibilityEvent(NumberPicker.this, event); 2490a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov } 2491d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2492d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2493d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void sendAccessibilityEventForVirtualButton(int virtualViewId, int eventType, 2494d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov String text) { 2495a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov if (AccessibilityManager.getInstance(mContext).isEnabled()) { 2496a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov AccessibilityEvent event = AccessibilityEvent.obtain(eventType); 2497a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov event.setClassName(Button.class.getName()); 2498a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov event.setPackageName(mContext.getPackageName()); 2499a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov event.getText().add(text); 2500a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov event.setEnabled(NumberPicker.this.isEnabled()); 2501a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov event.setSource(NumberPicker.this, virtualViewId); 2502a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov requestSendAccessibilityEvent(NumberPicker.this, event); 2503a90927629881f0faf54c1003ebd38c27a730045eSvetoslav Ganov } 2504d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2505d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2506d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private void findAccessibilityNodeInfosByTextInChild(String searchedLowerCase, 2507d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int virtualViewId, List<AccessibilityNodeInfo> outResult) { 2508d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov switch (virtualViewId) { 2509d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_DECREMENT: { 2510d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov String text = getVirtualDecrementButtonText(); 2511d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!TextUtils.isEmpty(text) 2512d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov && text.toString().toLowerCase().contains(searchedLowerCase)) { 2513d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov outResult.add(createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT)); 2514d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2515d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } return; 2516d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INPUT: { 2517d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov CharSequence text = mInputText.getText(); 2518d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!TextUtils.isEmpty(text) && 2519d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov text.toString().toLowerCase().contains(searchedLowerCase)) { 2520d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov outResult.add(createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT)); 2521d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return; 2522d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2523d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov CharSequence contentDesc = mInputText.getText(); 2524d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!TextUtils.isEmpty(contentDesc) && 2525d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov contentDesc.toString().toLowerCase().contains(searchedLowerCase)) { 2526d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov outResult.add(createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT)); 2527d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return; 2528d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2529d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } break; 2530d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov case VIRTUAL_VIEW_ID_INCREMENT: { 2531d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov String text = getVirtualIncrementButtonText(); 2532d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (!TextUtils.isEmpty(text) 2533d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov && text.toString().toLowerCase().contains(searchedLowerCase)) { 2534d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov outResult.add(createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT)); 2535d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2536d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } return; 2537d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2538d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2539d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 25400e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette private AccessibilityNodeInfo createAccessibiltyNodeInfoForInputText( 25410e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette int left, int top, int right, int bottom) { 2542d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov AccessibilityNodeInfo info = mInputText.createAccessibilityNodeInfo(); 2543d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT); 2544791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView != VIRTUAL_VIEW_ID_INPUT) { 2545791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 2546791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2547791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView == VIRTUAL_VIEW_ID_INPUT) { 2548791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 2549791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 25500e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette Rect boundsInParent = mTempRect; 25510e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette boundsInParent.set(left, top, right, bottom); 25520e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette info.setVisibleToUser(isVisibleToUser(boundsInParent)); 25530e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette info.setBoundsInParent(boundsInParent); 25540e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette Rect boundsInScreen = boundsInParent; 25550e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette int[] locationOnScreen = mTempArray; 25560e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette getLocationOnScreen(locationOnScreen); 25570e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]); 25580e2d281083e375d3b0bd44d61dbbef5c6d93921eAlan Viverette info.setBoundsInScreen(boundsInScreen); 2559d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return info; 2560d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2561d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2562d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private AccessibilityNodeInfo createAccessibilityNodeInfoForVirtualButton(int virtualViewId, 2563d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov String text, int left, int top, int right, int bottom) { 2564d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); 2565d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setClassName(Button.class.getName()); 2566d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setPackageName(mContext.getPackageName()); 2567d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setSource(NumberPicker.this, virtualViewId); 2568d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setParent(NumberPicker.this); 2569d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setText(text); 2570d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setClickable(true); 2571d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setLongClickable(true); 2572d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setEnabled(NumberPicker.this.isEnabled()); 2573d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov Rect boundsInParent = mTempRect; 2574d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov boundsInParent.set(left, top, right, bottom); 25750d607fbe546ac943de38dad33ae681b09efec6eaGuang Zhu info.setVisibleToUser(isVisibleToUser(boundsInParent)); 2576d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setBoundsInParent(boundsInParent); 2577d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov Rect boundsInScreen = boundsInParent; 2578d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int[] locationOnScreen = mTempArray; 2579d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov getLocationOnScreen(locationOnScreen); 2580d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]); 2581d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setBoundsInScreen(boundsInScreen); 2582791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2583791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView != virtualViewId) { 2584791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 2585791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2586791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView == virtualViewId) { 2587791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 2588791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2589fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled()) { 2590fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_CLICK); 2591fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov } 2592791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2593d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return info; 2594d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2595d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2596d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private AccessibilityNodeInfo createAccessibilityNodeInfoForNumberPicker(int left, int top, 2597d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int right, int bottom) { 2598d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); 25990d607fbe546ac943de38dad33ae681b09efec6eaGuang Zhu info.setClassName(NumberPicker.class.getName()); 2600d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setPackageName(mContext.getPackageName()); 2601d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setSource(NumberPicker.this); 2602791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2603791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (hasVirtualDecrementButton()) { 2604791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_DECREMENT); 2605791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 26060d607fbe546ac943de38dad33ae681b09efec6eaGuang Zhu info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT); 2607791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (hasVirtualIncrementButton()) { 2608791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT); 2609791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2610791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 26114528b4e882584745f48263fa6626987e63832a2aSvetoslav Ganov info.setParent((View) getParentForAccessibility()); 2612d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setEnabled(NumberPicker.this.isEnabled()); 2613d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setScrollable(true); 2614983119ab22a18c743e4084dff27f35e3f490dd34Svetoslav Ganov 2615983119ab22a18c743e4084dff27f35e3f490dd34Svetoslav Ganov final float applicationScale = 2616983119ab22a18c743e4084dff27f35e3f490dd34Svetoslav Ganov getContext().getResources().getCompatibilityInfo().applicationScale; 2617983119ab22a18c743e4084dff27f35e3f490dd34Svetoslav Ganov 2618d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov Rect boundsInParent = mTempRect; 2619d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov boundsInParent.set(left, top, right, bottom); 2620983119ab22a18c743e4084dff27f35e3f490dd34Svetoslav Ganov boundsInParent.scale(applicationScale); 2621d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setBoundsInParent(boundsInParent); 2622983119ab22a18c743e4084dff27f35e3f490dd34Svetoslav Ganov 26230d607fbe546ac943de38dad33ae681b09efec6eaGuang Zhu info.setVisibleToUser(isVisibleToUser()); 2624983119ab22a18c743e4084dff27f35e3f490dd34Svetoslav Ganov 2625d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov Rect boundsInScreen = boundsInParent; 2626d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int[] locationOnScreen = mTempArray; 2627d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov getLocationOnScreen(locationOnScreen); 2628d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]); 2629983119ab22a18c743e4084dff27f35e3f490dd34Svetoslav Ganov boundsInScreen.scale(applicationScale); 2630d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov info.setBoundsInScreen(boundsInScreen); 2631791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2632791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView != View.NO_ID) { 2633791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 2634791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2635791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov if (mAccessibilityFocusedView == View.NO_ID) { 2636791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 2637791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2638fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (NumberPicker.this.isEnabled()) { 2639fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (getWrapSelectorWheel() || getValue() < getMaxValue()) { 2640fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); 2641fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov } 2642fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov if (getWrapSelectorWheel() || getValue() > getMinValue()) { 2643fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); 2644fb1e80a247221ee7e8f5c5deba04812021d9d07eSvetoslav Ganov } 264548d1586f4065fc9ab97a679da1e4f7c327c943f2Svetoslav Ganov } 2646791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2647d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return info; 2648d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2649d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2650791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov private boolean hasVirtualDecrementButton() { 2651791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return getWrapSelectorWheel() || getValue() > getMinValue(); 2652791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2653791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2654791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov private boolean hasVirtualIncrementButton() { 2655791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov return getWrapSelectorWheel() || getValue() < getMaxValue(); 2656791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov } 2657791fd31a68c59395952005886ba799169f80a29aSvetoslav Ganov 2658d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private String getVirtualDecrementButtonText() { 2659d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int value = mValue - 1; 2660d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mWrapSelectorWheel) { 2661d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov value = getWrappedSelectorIndex(value); 2662d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2663d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (value >= mMinValue) { 2664d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return (mDisplayedValues == null) ? formatNumber(value) 2665d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov : mDisplayedValues[value - mMinValue]; 2666d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2667d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return null; 2668d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2669d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov 2670d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov private String getVirtualIncrementButtonText() { 2671d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov int value = mValue + 1; 2672d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (mWrapSelectorWheel) { 2673d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov value = getWrappedSelectorIndex(value); 2674d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2675d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov if (value <= mMaxValue) { 2676d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return (mDisplayedValues == null) ? formatNumber(value) 2677d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov : mDisplayedValues[value - mMinValue]; 2678d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2679d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov return null; 2680d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2681d11e6151fe88314505fa7adca6278de2e772b11cSvetoslav Ganov } 2682d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio 2683d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio static private String formatNumberWithLocale(int value) { 2684d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio return String.format(Locale.getDefault(), "%d", value); 2685d88e3054d08b1f821bb2e27b2647aa16a60d8742Fabrice Di Meglio } 26867762d93621f508f4410fd37b5bbdfec0071b0420Paul Westbrook} 2687