Fields Summary |
---|
private static final int | SELECTOR_WHEEL_ITEM_COUNTThe number of items show in the selector wheel. |
private static final long | DEFAULT_LONG_PRESS_UPDATE_INTERVALThe default update interval during long press. |
private static final int | SELECTOR_MIDDLE_ITEM_INDEXThe index of the middle selector item. |
private static final int | SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENTThe coefficient by which to adjust (divide) the max fling velocity. |
private static final int | SELECTOR_ADJUSTMENT_DURATION_MILLISThe the duration for adjusting the selector wheel. |
private static final int | SNAP_SCROLL_DURATIONThe duration of scrolling while snapping to a given position. |
private static final float | TOP_AND_BOTTOM_FADING_EDGE_STRENGTHThe strength of fading in the top and bottom while drawing the selector. |
private static final int | UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHTThe default unscaled height of the selection divider. |
private static final int | UNSCALED_DEFAULT_SELECTION_DIVIDERS_DISTANCEThe default unscaled distance between the selection dividers. |
private static final int | DEFAULT_LAYOUT_RESOURCE_IDThe resource id for the default layout. |
private static final int | SIZE_UNSPECIFIEDConstant for unspecified size. |
private static final TwoDigitFormatter | sTwoDigitFormatter |
private final ImageButton | mIncrementButtonThe increment button. |
private final ImageButton | mDecrementButtonThe decrement button. |
private final EditText | mInputTextThe text for showing the current value. |
private final int | mSelectionDividersDistanceThe distance between the two selection dividers. |
private final int | mMinHeightThe min height of this widget. |
private final int | mMaxHeightThe max height of this widget. |
private final int | mMinWidthThe max width of this widget. |
private int | mMaxWidthThe max width of this widget. |
private final boolean | mComputeMaxWidthFlag whether to compute the max width. |
private final int | mTextSizeThe height of the text. |
private int | mSelectorTextGapHeightThe height of the gap between text elements if the selector wheel. |
private String[] | mDisplayedValuesThe values to be displayed instead the indices. |
private int | mMinValueLower value of the range of numbers allowed for the NumberPicker |
private int | mMaxValueUpper value of the range of numbers allowed for the NumberPicker |
private int | mValueCurrent value of this NumberPicker |
private OnValueChangeListener | mOnValueChangeListenerListener to be notified upon current value change. |
private OnScrollListener | mOnScrollListenerListener to be notified upon scroll state change. |
private Formatter | mFormatterFormatter for for displaying the current value. |
private long | mLongPressUpdateIntervalThe speed for updating the value form long press. |
private final android.util.SparseArray | mSelectorIndexToStringCacheCache for the string representation of selector indices. |
private final int[] | mSelectorIndicesThe selector indices whose value are show by the selector. |
private final android.graphics.Paint | mSelectorWheelPaintThe {@link Paint} for drawing the selector. |
private final android.graphics.drawable.Drawable | mVirtualButtonPressedDrawableThe {@link Drawable} for pressed virtual (increment/decrement) buttons. |
private int | mSelectorElementHeightThe height of a selector element (text + gap). |
private int | mInitialScrollOffsetThe initial offset of the scroll selector. |
private int | mCurrentScrollOffsetThe current offset of the scroll selector. |
private final Scroller | mFlingScrollerThe {@link Scroller} responsible for flinging the selector. |
private final Scroller | mAdjustScrollerThe {@link Scroller} responsible for adjusting the selector. |
private int | mPreviousScrollerYThe previous Y coordinate while scrolling the selector. |
private SetSelectionCommand | mSetSelectionCommandHandle to the reusable command for setting the input text selection. |
private ChangeCurrentByOneFromLongPressCommand | mChangeCurrentByOneFromLongPressCommandHandle to the reusable command for changing the current value from long
press by one. |
private BeginSoftInputOnLongPressCommand | mBeginSoftInputOnLongPressCommandCommand for beginning an edit of the current value via IME on long press. |
private float | mLastDownEventYThe Y position of the last down event. |
private long | mLastDownEventTimeThe time of the last down event. |
private float | mLastDownOrMoveEventYThe Y position of the last down or move event. |
private android.view.VelocityTracker | mVelocityTrackerDetermines speed during touch scrolling. |
private int | mTouchSlop |
private int | mMinimumFlingVelocity |
private int | mMaximumFlingVelocity |
private boolean | mWrapSelectorWheelFlag whether the selector should wrap around. |
private final int | mSolidColorThe back ground color used to optimize scroller fading. |
private final boolean | mHasSelectorWheelFlag whether this widget has a selector wheel. |
private final android.graphics.drawable.Drawable | mSelectionDividerDivider for showing item to be selected while scrolling |
private final int | mSelectionDividerHeightThe height of the selection divider. |
private int | mScrollStateThe current scroll state of the number picker. |
private boolean | mIgnoreMoveEventsFlag whether to ignore move events - we ignore such when we show in IME
to prevent the content from scrolling. |
private boolean | mPerformClickOnTapFlag whether to perform a click on tap. |
private int | mTopSelectionDividerTopThe top of the top selection divider. |
private int | mBottomSelectionDividerBottomThe bottom of the bottom selection divider. |
private int | mLastHoveredChildVirtualViewIdThe virtual id of the last hovered child. |
private boolean | mIncrementVirtualButtonPressedWhether the increment virtual button is pressed. |
private boolean | mDecrementVirtualButtonPressedWhether the decrement virtual button is pressed. |
private AccessibilityNodeProviderImpl | mAccessibilityNodeProviderProvider to report to clients the semantic structure of this widget. |
private final PressedStateHelper | mPressedStateHelperHelper class for managing pressed state of the virtual buttons. |
private int | mLastHandledDownDpadKeyCodeThe keycode of the last handled DPAD down event. |
private boolean | mHideWheelUntilFocusedIf true then the selector wheel is hidden until the picker has focus. |
private static final char[] | DIGIT_CHARACTERSThe numbers accepted by the input text's {@link Filter} |
Methods Summary |
---|
private void | changeValueByOne(boolean increment)Changes the current value by one which is increment or
decrement based on the passes argument.
decrement the current value.
if (mHasSelectorWheel) {
mInputText.setVisibility(View.INVISIBLE);
if (!moveToFinalScrollerPosition(mFlingScroller)) {
moveToFinalScrollerPosition(mAdjustScroller);
}
mPreviousScrollerY = 0;
if (increment) {
mFlingScroller.startScroll(0, 0, 0, -mSelectorElementHeight, SNAP_SCROLL_DURATION);
} else {
mFlingScroller.startScroll(0, 0, 0, mSelectorElementHeight, SNAP_SCROLL_DURATION);
}
invalidate();
} else {
if (increment) {
setValueInternal(mValue + 1, true);
} else {
setValueInternal(mValue - 1, true);
}
}
|
public void | computeScroll()
Scroller scroller = mFlingScroller;
if (scroller.isFinished()) {
scroller = mAdjustScroller;
if (scroller.isFinished()) {
return;
}
}
scroller.computeScrollOffset();
int currentScrollerY = scroller.getCurrY();
if (mPreviousScrollerY == 0) {
mPreviousScrollerY = scroller.getStartY();
}
scrollBy(0, currentScrollerY - mPreviousScrollerY);
mPreviousScrollerY = currentScrollerY;
if (scroller.isFinished()) {
onScrollerFinished(scroller);
} else {
invalidate();
}
|
protected int | computeVerticalScrollExtent()
return getHeight();
|
protected int | computeVerticalScrollOffset()
return mCurrentScrollOffset;
|
protected int | computeVerticalScrollRange()
return (mMaxValue - mMinValue + 1) * mSelectorElementHeight;
|
private void | decrementSelectorIndices(int[] selectorIndices)Decrements the selectorIndices whose string representations
will be displayed in the selector.
for (int i = selectorIndices.length - 1; i > 0; i--) {
selectorIndices[i] = selectorIndices[i - 1];
}
int nextScrollSelectorIndex = selectorIndices[1] - 1;
if (mWrapSelectorWheel && nextScrollSelectorIndex < mMinValue) {
nextScrollSelectorIndex = mMaxValue;
}
selectorIndices[0] = nextScrollSelectorIndex;
ensureCachedScrollSelectorValue(nextScrollSelectorIndex);
|
protected boolean | dispatchHoverEvent(android.view.MotionEvent event)
if (!mHasSelectorWheel) {
return super.dispatchHoverEvent(event);
}
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
final int eventY = (int) event.getY();
final int hoveredVirtualViewId;
if (eventY < mTopSelectionDividerTop) {
hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_DECREMENT;
} else if (eventY > mBottomSelectionDividerBottom) {
hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_INCREMENT;
} else {
hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_INPUT;
}
final int action = event.getActionMasked();
AccessibilityNodeProviderImpl provider =
(AccessibilityNodeProviderImpl) getAccessibilityNodeProvider();
switch (action) {
case MotionEvent.ACTION_HOVER_ENTER: {
provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
mLastHoveredChildVirtualViewId = hoveredVirtualViewId;
provider.performAction(hoveredVirtualViewId,
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
} break;
case MotionEvent.ACTION_HOVER_MOVE: {
if (mLastHoveredChildVirtualViewId != hoveredVirtualViewId
&& mLastHoveredChildVirtualViewId != View.NO_ID) {
provider.sendAccessibilityEventForVirtualView(
mLastHoveredChildVirtualViewId,
AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
mLastHoveredChildVirtualViewId = hoveredVirtualViewId;
provider.performAction(hoveredVirtualViewId,
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
}
} break;
case MotionEvent.ACTION_HOVER_EXIT: {
provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
mLastHoveredChildVirtualViewId = View.NO_ID;
} break;
}
}
return false;
|
public boolean | dispatchKeyEvent(android.view.KeyEvent event)
final int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
removeAllCallbacks();
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_UP:
if (!mHasSelectorWheel) {
break;
}
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
if (mWrapSelectorWheel || ((keyCode == KeyEvent.KEYCODE_DPAD_DOWN)
? getValue() < getMaxValue() : getValue() > getMinValue())) {
requestFocus();
mLastHandledDownDpadKeyCode = keyCode;
removeAllCallbacks();
if (mFlingScroller.isFinished()) {
changeValueByOne(keyCode == KeyEvent.KEYCODE_DPAD_DOWN);
}
return true;
}
break;
case KeyEvent.ACTION_UP:
if (mLastHandledDownDpadKeyCode == keyCode) {
mLastHandledDownDpadKeyCode = -1;
return true;
}
break;
}
}
return super.dispatchKeyEvent(event);
|
public boolean | dispatchTouchEvent(android.view.MotionEvent event)
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
removeAllCallbacks();
break;
}
return super.dispatchTouchEvent(event);
|
public boolean | dispatchTrackballEvent(android.view.MotionEvent event)
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
removeAllCallbacks();
break;
}
return super.dispatchTrackballEvent(event);
|
private void | ensureCachedScrollSelectorValue(int selectorIndex)Ensures we have a cached string representation of the given
selectorIndex to avoid multiple instantiations of the same string.
SparseArray<String> cache = mSelectorIndexToStringCache;
String scrollSelectorValue = cache.get(selectorIndex);
if (scrollSelectorValue != null) {
return;
}
if (selectorIndex < mMinValue || selectorIndex > mMaxValue) {
scrollSelectorValue = "";
} else {
if (mDisplayedValues != null) {
int displayedValueIndex = selectorIndex - mMinValue;
scrollSelectorValue = mDisplayedValues[displayedValueIndex];
} else {
scrollSelectorValue = formatNumber(selectorIndex);
}
}
cache.put(selectorIndex, scrollSelectorValue);
|
private boolean | ensureScrollWheelAdjusted()Ensures that the scroll wheel is adjusted i.e. there is no offset and the
middle element is in the middle of the widget.
// adjust to the closest value
int deltaY = mInitialScrollOffset - mCurrentScrollOffset;
if (deltaY != 0) {
mPreviousScrollerY = 0;
if (Math.abs(deltaY) > mSelectorElementHeight / 2) {
deltaY += (deltaY > 0) ? -mSelectorElementHeight : mSelectorElementHeight;
}
mAdjustScroller.startScroll(0, 0, 0, deltaY, SELECTOR_ADJUSTMENT_DURATION_MILLIS);
invalidate();
return true;
}
return false;
|
private void | fling(int velocityY)Flings the selector with the given velocityY .
mPreviousScrollerY = 0;
if (velocityY > 0) {
mFlingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
} else {
mFlingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
}
invalidate();
|
private java.lang.String | formatNumber(int value)
return (mFormatter != null) ? mFormatter.format(value) : formatNumberWithLocale(value);
|
private static java.lang.String | formatNumberWithLocale(int value)
return String.format(Locale.getDefault(), "%d", value);
|
public android.view.accessibility.AccessibilityNodeProvider | getAccessibilityNodeProvider()
if (!mHasSelectorWheel) {
return super.getAccessibilityNodeProvider();
}
if (mAccessibilityNodeProvider == null) {
mAccessibilityNodeProvider = new AccessibilityNodeProviderImpl();
}
return mAccessibilityNodeProvider;
|
protected float | getBottomFadingEdgeStrength()
return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH;
|
public java.lang.String[] | getDisplayedValues()Gets the values to be displayed instead of string values.
return mDisplayedValues;
|
public int | getMaxValue()Returns the max value of the picker.
return mMaxValue;
|
public int | getMinValue()Returns the min value of the picker.
return mMinValue;
|
private int | getSelectedPos(java.lang.String value)
if (mDisplayedValues == null) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
// Ignore as if it's not a number we don't care
}
} else {
for (int i = 0; i < mDisplayedValues.length; i++) {
// Don't force the user to type in jan when ja will do
value = value.toLowerCase();
if (mDisplayedValues[i].toLowerCase().startsWith(value)) {
return mMinValue + i;
}
}
/*
* The user might have typed in a number into the month field i.e.
* 10 instead of OCT so support that too.
*/
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
// Ignore as if it's not a number we don't care
}
}
return mMinValue;
|
public int | getSolidColor()
return mSolidColor;
|
protected float | getTopFadingEdgeStrength()
return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH;
|
public static final android.widget.NumberPicker$Formatter | getTwoDigitFormatter()
return sTwoDigitFormatter;
|
public int | getValue()Returns the value of the picker.
return mValue;
|
public boolean | getWrapSelectorWheel()Gets whether the selector wheel wraps when reaching the min/max value.
return mWrapSelectorWheel;
|
private int | getWrappedSelectorIndex(int selectorIndex)
if (selectorIndex > mMaxValue) {
return mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1;
} else if (selectorIndex < mMinValue) {
return mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1;
}
return selectorIndex;
|
private void | hideSoftInput()Hides the soft input if it is active for the input text.
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
if (inputMethodManager != null && inputMethodManager.isActive(mInputText)) {
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
if (mHasSelectorWheel) {
mInputText.setVisibility(View.INVISIBLE);
}
}
|
private void | incrementSelectorIndices(int[] selectorIndices)Increments the selectorIndices whose string representations
will be displayed in the selector.
for (int i = 0; i < selectorIndices.length - 1; i++) {
selectorIndices[i] = selectorIndices[i + 1];
}
int nextScrollSelectorIndex = selectorIndices[selectorIndices.length - 2] + 1;
if (mWrapSelectorWheel && nextScrollSelectorIndex > mMaxValue) {
nextScrollSelectorIndex = mMinValue;
}
selectorIndices[selectorIndices.length - 1] = nextScrollSelectorIndex;
ensureCachedScrollSelectorValue(nextScrollSelectorIndex);
|
private void | initializeFadingEdges()
setVerticalFadingEdgeEnabled(true);
setFadingEdgeLength((mBottom - mTop - mTextSize) / 2);
|
private void | initializeSelectorWheel()
initializeSelectorWheelIndices();
int[] selectorIndices = mSelectorIndices;
int totalTextHeight = selectorIndices.length * mTextSize;
float totalTextGapHeight = (mBottom - mTop) - totalTextHeight;
float textGapCount = selectorIndices.length;
mSelectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f);
mSelectorElementHeight = mTextSize + mSelectorTextGapHeight;
// Ensure that the middle item is positioned the same as the text in
// mInputText
int editTextTextPosition = mInputText.getBaseline() + mInputText.getTop();
mInitialScrollOffset = editTextTextPosition
- (mSelectorElementHeight * SELECTOR_MIDDLE_ITEM_INDEX);
mCurrentScrollOffset = mInitialScrollOffset;
updateInputTextView();
|
private void | initializeSelectorWheelIndices()Resets the selector indices and clear the cached string representation of
these indices.
mSelectorIndexToStringCache.clear();
int[] selectorIndices = mSelectorIndices;
int current = getValue();
for (int i = 0; i < mSelectorIndices.length; i++) {
int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX);
if (mWrapSelectorWheel) {
selectorIndex = getWrappedSelectorIndex(selectorIndex);
}
selectorIndices[i] = selectorIndex;
ensureCachedScrollSelectorValue(selectorIndices[i]);
}
|
private int | makeMeasureSpec(int measureSpec, int maxSize)Makes a measure spec that tries greedily to use the max value.
if (maxSize == SIZE_UNSPECIFIED) {
return measureSpec;
}
final int size = MeasureSpec.getSize(measureSpec);
final int mode = MeasureSpec.getMode(measureSpec);
switch (mode) {
case MeasureSpec.EXACTLY:
return measureSpec;
case MeasureSpec.AT_MOST:
return MeasureSpec.makeMeasureSpec(Math.min(size, maxSize), MeasureSpec.EXACTLY);
case MeasureSpec.UNSPECIFIED:
return MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.EXACTLY);
default:
throw new IllegalArgumentException("Unknown measure mode: " + mode);
}
|
private boolean | moveToFinalScrollerPosition(Scroller scroller)Move to the final position of a scroller. Ensures to force finish the scroller
and if it is not at its final position a scroll of the selector wheel is
performed to fast forward to the final position.
scroller.forceFinished(true);
int amountToScroll = scroller.getFinalY() - scroller.getCurrY();
int futureScrollOffset = (mCurrentScrollOffset + amountToScroll) % mSelectorElementHeight;
int overshootAdjustment = mInitialScrollOffset - futureScrollOffset;
if (overshootAdjustment != 0) {
if (Math.abs(overshootAdjustment) > mSelectorElementHeight / 2) {
if (overshootAdjustment > 0) {
overshootAdjustment -= mSelectorElementHeight;
} else {
overshootAdjustment += mSelectorElementHeight;
}
}
amountToScroll += overshootAdjustment;
scrollBy(0, amountToScroll);
return true;
}
return false;
|
private void | notifyChange(int previous, int current)Notifies the listener, if registered, of a change of the value of this
NumberPicker.
if (mOnValueChangeListener != null) {
mOnValueChangeListener.onValueChange(this, previous, mValue);
}
|
protected void | onDetachedFromWindow()
super.onDetachedFromWindow();
removeAllCallbacks();
|
protected void | onDraw(android.graphics.Canvas canvas)
if (!mHasSelectorWheel) {
super.onDraw(canvas);
return;
}
final boolean showSelectorWheel = mHideWheelUntilFocused ? hasFocus() : true;
float x = (mRight - mLeft) / 2;
float y = mCurrentScrollOffset;
// draw the virtual buttons pressed state if needed
if (showSelectorWheel && mVirtualButtonPressedDrawable != null
&& mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
if (mDecrementVirtualButtonPressed) {
mVirtualButtonPressedDrawable.setState(PRESSED_STATE_SET);
mVirtualButtonPressedDrawable.setBounds(0, 0, mRight, mTopSelectionDividerTop);
mVirtualButtonPressedDrawable.draw(canvas);
}
if (mIncrementVirtualButtonPressed) {
mVirtualButtonPressedDrawable.setState(PRESSED_STATE_SET);
mVirtualButtonPressedDrawable.setBounds(0, mBottomSelectionDividerBottom, mRight,
mBottom);
mVirtualButtonPressedDrawable.draw(canvas);
}
}
// draw the selector wheel
int[] selectorIndices = mSelectorIndices;
for (int i = 0; i < selectorIndices.length; i++) {
int selectorIndex = selectorIndices[i];
String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex);
// Do not draw the middle item if input is visible since the input
// is shown only if the wheel is static and it covers the middle
// item. Otherwise, if the user starts editing the text via the
// IME he may see a dimmed version of the old value intermixed
// with the new one.
if ((showSelectorWheel && i != SELECTOR_MIDDLE_ITEM_INDEX) ||
(i == SELECTOR_MIDDLE_ITEM_INDEX && mInputText.getVisibility() != VISIBLE)) {
canvas.drawText(scrollSelectorValue, x, y, mSelectorWheelPaint);
}
y += mSelectorElementHeight;
}
// draw the selection dividers
if (showSelectorWheel && mSelectionDivider != null) {
// draw the top divider
int topOfTopDivider = mTopSelectionDividerTop;
int bottomOfTopDivider = topOfTopDivider + mSelectionDividerHeight;
mSelectionDivider.setBounds(0, topOfTopDivider, mRight, bottomOfTopDivider);
mSelectionDivider.draw(canvas);
// draw the bottom divider
int bottomOfBottomDivider = mBottomSelectionDividerBottom;
int topOfBottomDivider = bottomOfBottomDivider - mSelectionDividerHeight;
mSelectionDivider.setBounds(0, topOfBottomDivider, mRight, bottomOfBottomDivider);
mSelectionDivider.draw(canvas);
}
|
public void | onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)
super.onInitializeAccessibilityEvent(event);
event.setClassName(NumberPicker.class.getName());
event.setScrollable(true);
event.setScrollY((mMinValue + mValue) * mSelectorElementHeight);
event.setMaxScrollY((mMaxValue - mMinValue) * mSelectorElementHeight);
|
public boolean | onInterceptTouchEvent(android.view.MotionEvent event)
if (!mHasSelectorWheel || !isEnabled()) {
return false;
}
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN: {
removeAllCallbacks();
mInputText.setVisibility(View.INVISIBLE);
mLastDownOrMoveEventY = mLastDownEventY = event.getY();
mLastDownEventTime = event.getEventTime();
mIgnoreMoveEvents = false;
mPerformClickOnTap = false;
// Handle pressed state before any state change.
if (mLastDownEventY < mTopSelectionDividerTop) {
if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
mPressedStateHelper.buttonPressDelayed(
PressedStateHelper.BUTTON_DECREMENT);
}
} else if (mLastDownEventY > mBottomSelectionDividerBottom) {
if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
mPressedStateHelper.buttonPressDelayed(
PressedStateHelper.BUTTON_INCREMENT);
}
}
// Make sure we support flinging inside scrollables.
getParent().requestDisallowInterceptTouchEvent(true);
if (!mFlingScroller.isFinished()) {
mFlingScroller.forceFinished(true);
mAdjustScroller.forceFinished(true);
onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
} else if (!mAdjustScroller.isFinished()) {
mFlingScroller.forceFinished(true);
mAdjustScroller.forceFinished(true);
} else if (mLastDownEventY < mTopSelectionDividerTop) {
hideSoftInput();
postChangeCurrentByOneFromLongPress(
false, ViewConfiguration.getLongPressTimeout());
} else if (mLastDownEventY > mBottomSelectionDividerBottom) {
hideSoftInput();
postChangeCurrentByOneFromLongPress(
true, ViewConfiguration.getLongPressTimeout());
} else {
mPerformClickOnTap = true;
postBeginSoftInputOnLongPressCommand();
}
return true;
}
}
return false;
|
protected void | onLayout(boolean changed, int left, int top, int right, int bottom)
if (!mHasSelectorWheel) {
super.onLayout(changed, left, top, right, bottom);
return;
}
final int msrdWdth = getMeasuredWidth();
final int msrdHght = getMeasuredHeight();
// Input text centered horizontally.
final int inptTxtMsrdWdth = mInputText.getMeasuredWidth();
final int inptTxtMsrdHght = mInputText.getMeasuredHeight();
final int inptTxtLeft = (msrdWdth - inptTxtMsrdWdth) / 2;
final int inptTxtTop = (msrdHght - inptTxtMsrdHght) / 2;
final int inptTxtRight = inptTxtLeft + inptTxtMsrdWdth;
final int inptTxtBottom = inptTxtTop + inptTxtMsrdHght;
mInputText.layout(inptTxtLeft, inptTxtTop, inptTxtRight, inptTxtBottom);
if (changed) {
// need to do all this when we know our size
initializeSelectorWheel();
initializeFadingEdges();
mTopSelectionDividerTop = (getHeight() - mSelectionDividersDistance) / 2
- mSelectionDividerHeight;
mBottomSelectionDividerBottom = mTopSelectionDividerTop + 2 * mSelectionDividerHeight
+ mSelectionDividersDistance;
}
|
protected void | onMeasure(int widthMeasureSpec, int heightMeasureSpec)
if (!mHasSelectorWheel) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
// Try greedily to fit the max width and height.
final int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMaxWidth);
final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight);
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
// Flag if we are measured with width or height less than the respective min.
final int widthSize = resolveSizeAndStateRespectingMinSize(mMinWidth, getMeasuredWidth(),
widthMeasureSpec);
final int heightSize = resolveSizeAndStateRespectingMinSize(mMinHeight, getMeasuredHeight(),
heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
|
private void | onScrollStateChange(int scrollState)Handles transition to a given scrollState
if (mScrollState == scrollState) {
return;
}
mScrollState = scrollState;
if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChange(this, scrollState);
}
|
private void | onScrollerFinished(Scroller scroller)Callback invoked upon completion of a given scroller .
if (scroller == mFlingScroller) {
if (!ensureScrollWheelAdjusted()) {
updateInputTextView();
}
onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
} else {
if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
updateInputTextView();
}
}
|
public boolean | onTouchEvent(android.view.MotionEvent event)
if (!isEnabled() || !mHasSelectorWheel) {
return false;
}
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_MOVE: {
if (mIgnoreMoveEvents) {
break;
}
float currentMoveY = event.getY();
if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY);
if (deltaDownY > mTouchSlop) {
removeAllCallbacks();
onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
} else {
int deltaMoveY = (int) ((currentMoveY - mLastDownOrMoveEventY));
scrollBy(0, deltaMoveY);
invalidate();
}
mLastDownOrMoveEventY = currentMoveY;
} break;
case MotionEvent.ACTION_UP: {
removeBeginSoftInputCommand();
removeChangeCurrentByOneFromLongPress();
mPressedStateHelper.cancel();
VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
int initialVelocity = (int) velocityTracker.getYVelocity();
if (Math.abs(initialVelocity) > mMinimumFlingVelocity) {
fling(initialVelocity);
onScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
} else {
int eventY = (int) event.getY();
int deltaMoveY = (int) Math.abs(eventY - mLastDownEventY);
long deltaTime = event.getEventTime() - mLastDownEventTime;
if (deltaMoveY <= mTouchSlop && deltaTime < ViewConfiguration.getTapTimeout()) {
if (mPerformClickOnTap) {
mPerformClickOnTap = false;
performClick();
} else {
int selectorIndexOffset = (eventY / mSelectorElementHeight)
- SELECTOR_MIDDLE_ITEM_INDEX;
if (selectorIndexOffset > 0) {
changeValueByOne(true);
mPressedStateHelper.buttonTapped(
PressedStateHelper.BUTTON_INCREMENT);
} else if (selectorIndexOffset < 0) {
changeValueByOne(false);
mPressedStateHelper.buttonTapped(
PressedStateHelper.BUTTON_DECREMENT);
}
}
} else {
ensureScrollWheelAdjusted();
}
onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
}
mVelocityTracker.recycle();
mVelocityTracker = null;
} break;
}
return true;
|
public boolean | performClick()
if (!mHasSelectorWheel) {
return super.performClick();
} else if (!super.performClick()) {
showSoftInput();
}
return true;
|
public boolean | performLongClick()
if (!mHasSelectorWheel) {
return super.performLongClick();
} else if (!super.performLongClick()) {
showSoftInput();
mIgnoreMoveEvents = true;
}
return true;
|
private void | postBeginSoftInputOnLongPressCommand()Posts a command for beginning an edit of the current value via IME on
long press.
if (mBeginSoftInputOnLongPressCommand == null) {
mBeginSoftInputOnLongPressCommand = new BeginSoftInputOnLongPressCommand();
} else {
removeCallbacks(mBeginSoftInputOnLongPressCommand);
}
postDelayed(mBeginSoftInputOnLongPressCommand, ViewConfiguration.getLongPressTimeout());
|
private void | postChangeCurrentByOneFromLongPress(boolean increment, long delayMillis)Posts a command for changing the current value by one.
if (mChangeCurrentByOneFromLongPressCommand == null) {
mChangeCurrentByOneFromLongPressCommand = new ChangeCurrentByOneFromLongPressCommand();
} else {
removeCallbacks(mChangeCurrentByOneFromLongPressCommand);
}
mChangeCurrentByOneFromLongPressCommand.setStep(increment);
postDelayed(mChangeCurrentByOneFromLongPressCommand, delayMillis);
|
private void | postSetSelectionCommand(int selectionStart, int selectionEnd)Posts an {@link SetSelectionCommand} from the given selectionStart
to selectionEnd .
if (mSetSelectionCommand == null) {
mSetSelectionCommand = new SetSelectionCommand();
} else {
removeCallbacks(mSetSelectionCommand);
}
mSetSelectionCommand.mSelectionStart = selectionStart;
mSetSelectionCommand.mSelectionEnd = selectionEnd;
post(mSetSelectionCommand);
|
private void | removeAllCallbacks()Removes all pending callback from the message queue.
if (mChangeCurrentByOneFromLongPressCommand != null) {
removeCallbacks(mChangeCurrentByOneFromLongPressCommand);
}
if (mSetSelectionCommand != null) {
removeCallbacks(mSetSelectionCommand);
}
if (mBeginSoftInputOnLongPressCommand != null) {
removeCallbacks(mBeginSoftInputOnLongPressCommand);
}
mPressedStateHelper.cancel();
|
private void | removeBeginSoftInputCommand()Removes the command for beginning an edit of the current value via IME.
if (mBeginSoftInputOnLongPressCommand != null) {
removeCallbacks(mBeginSoftInputOnLongPressCommand);
}
|
private void | removeChangeCurrentByOneFromLongPress()Removes the command for changing the current value by one.
if (mChangeCurrentByOneFromLongPressCommand != null) {
removeCallbacks(mChangeCurrentByOneFromLongPressCommand);
}
|
private int | resolveSizeAndStateRespectingMinSize(int minSize, int measuredSize, int measureSpec)Utility to reconcile a desired size and state, with constraints imposed
by a MeasureSpec. Tries to respect the min size, unless a different size
is imposed by the constraints.
if (minSize != SIZE_UNSPECIFIED) {
final int desiredWidth = Math.max(minSize, measuredSize);
return resolveSizeAndState(desiredWidth, measureSpec, 0);
} else {
return measuredSize;
}
|
public void | scrollBy(int x, int y)
int[] selectorIndices = mSelectorIndices;
if (!mWrapSelectorWheel && y > 0
&& selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) {
mCurrentScrollOffset = mInitialScrollOffset;
return;
}
if (!mWrapSelectorWheel && y < 0
&& selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) {
mCurrentScrollOffset = mInitialScrollOffset;
return;
}
mCurrentScrollOffset += y;
while (mCurrentScrollOffset - mInitialScrollOffset > mSelectorTextGapHeight) {
mCurrentScrollOffset -= mSelectorElementHeight;
decrementSelectorIndices(selectorIndices);
setValueInternal(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX], true);
if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) {
mCurrentScrollOffset = mInitialScrollOffset;
}
}
while (mCurrentScrollOffset - mInitialScrollOffset < -mSelectorTextGapHeight) {
mCurrentScrollOffset += mSelectorElementHeight;
incrementSelectorIndices(selectorIndices);
setValueInternal(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX], true);
if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) {
mCurrentScrollOffset = mInitialScrollOffset;
}
}
|
public void | setDisplayedValues(java.lang.String[] displayedValues)Sets the values to be displayed.
if (mDisplayedValues == displayedValues) {
return;
}
mDisplayedValues = displayedValues;
if (mDisplayedValues != null) {
// Allow text entry rather than strictly numeric entry.
mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
} else {
mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
}
updateInputTextView();
initializeSelectorWheelIndices();
tryComputeMaxWidth();
|
public void | setEnabled(boolean enabled)
super.setEnabled(enabled);
if (!mHasSelectorWheel) {
mIncrementButton.setEnabled(enabled);
}
if (!mHasSelectorWheel) {
mDecrementButton.setEnabled(enabled);
}
mInputText.setEnabled(enabled);
|
public void | setFormatter(android.widget.NumberPicker$Formatter formatter)Set the formatter to be used for formatting the current value.
Note: If you have provided alternative values for the values this
formatter is never invoked.
if (formatter == mFormatter) {
return;
}
mFormatter = formatter;
initializeSelectorWheelIndices();
updateInputTextView();
|
public void | setMaxValue(int maxValue)Sets the max value of the picker.
if (mMaxValue == maxValue) {
return;
}
if (maxValue < 0) {
throw new IllegalArgumentException("maxValue must be >= 0");
}
mMaxValue = maxValue;
if (mMaxValue < mValue) {
mValue = mMaxValue;
}
boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length;
setWrapSelectorWheel(wrapSelectorWheel);
initializeSelectorWheelIndices();
updateInputTextView();
tryComputeMaxWidth();
invalidate();
|
public void | setMinValue(int minValue)Sets the min value of the picker.
if (mMinValue == minValue) {
return;
}
if (minValue < 0) {
throw new IllegalArgumentException("minValue must be >= 0");
}
mMinValue = minValue;
if (mMinValue > mValue) {
mValue = mMinValue;
}
boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length;
setWrapSelectorWheel(wrapSelectorWheel);
initializeSelectorWheelIndices();
updateInputTextView();
tryComputeMaxWidth();
invalidate();
|
public void | setOnLongPressUpdateInterval(long intervalMillis)Sets the speed at which the numbers be incremented and decremented when
the up and down buttons are long pressed respectively.
The default value is 300 ms.
mLongPressUpdateInterval = intervalMillis;
|
public void | setOnScrollListener(android.widget.NumberPicker$OnScrollListener onScrollListener)Set listener to be notified for scroll state changes.
mOnScrollListener = onScrollListener;
|
public void | setOnValueChangedListener(android.widget.NumberPicker$OnValueChangeListener onValueChangedListener)Sets the listener to be notified on change of the current value.
mOnValueChangeListener = onValueChangedListener;
|
public void | setValue(int value)Set the current value for the number picker.
If the argument is less than the {@link NumberPicker#getMinValue()} and
{@link NumberPicker#getWrapSelectorWheel()} is false the
current value is set to the {@link NumberPicker#getMinValue()} value.
If the argument is less than the {@link NumberPicker#getMinValue()} and
{@link NumberPicker#getWrapSelectorWheel()} is true the
current value is set to the {@link NumberPicker#getMaxValue()} value.
If the argument is less than the {@link NumberPicker#getMaxValue()} and
{@link NumberPicker#getWrapSelectorWheel()} is false the
current value is set to the {@link NumberPicker#getMaxValue()} value.
If the argument is less than the {@link NumberPicker#getMaxValue()} and
{@link NumberPicker#getWrapSelectorWheel()} is true the
current value is set to the {@link NumberPicker#getMinValue()} value.
setValueInternal(value, false);
|
private void | setValueInternal(int current, boolean notifyChange)Sets the current value of this NumberPicker.
if (mValue == current) {
return;
}
// Wrap around the values if we go past the start or end
if (mWrapSelectorWheel) {
current = getWrappedSelectorIndex(current);
} else {
current = Math.max(current, mMinValue);
current = Math.min(current, mMaxValue);
}
int previous = mValue;
mValue = current;
updateInputTextView();
if (notifyChange) {
notifyChange(previous, current);
}
initializeSelectorWheelIndices();
invalidate();
|
public void | setWrapSelectorWheel(boolean wrapSelectorWheel)Sets whether the selector wheel shown during flinging/scrolling should
wrap around the {@link NumberPicker#getMinValue()} and
{@link NumberPicker#getMaxValue()} values.
By default if the range (max - min) is more than the number of items shown
on the selector wheel the selector wheel wrapping is enabled.
Note: If the number of items, i.e. the range (
{@link #getMaxValue()} - {@link #getMinValue()}) is less than
the number of items shown on the selector wheel, the selector wheel will
not wrap. Hence, in such a case calling this method is a NOP.
final boolean wrappingAllowed = (mMaxValue - mMinValue) >= mSelectorIndices.length;
if ((!wrapSelectorWheel || wrappingAllowed) && wrapSelectorWheel != mWrapSelectorWheel) {
mWrapSelectorWheel = wrapSelectorWheel;
}
|
private void | showSoftInput()Shows the soft input for its input text.
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
if (inputMethodManager != null) {
if (mHasSelectorWheel) {
mInputText.setVisibility(View.VISIBLE);
}
mInputText.requestFocus();
inputMethodManager.showSoftInput(mInputText, 0);
}
|
private void | tryComputeMaxWidth()Computes the max width if no such specified as an attribute.
if (!mComputeMaxWidth) {
return;
}
int maxTextWidth = 0;
if (mDisplayedValues == null) {
float maxDigitWidth = 0;
for (int i = 0; i <= 9; i++) {
final float digitWidth = mSelectorWheelPaint.measureText(formatNumberWithLocale(i));
if (digitWidth > maxDigitWidth) {
maxDigitWidth = digitWidth;
}
}
int numberOfDigits = 0;
int current = mMaxValue;
while (current > 0) {
numberOfDigits++;
current = current / 10;
}
maxTextWidth = (int) (numberOfDigits * maxDigitWidth);
} else {
final int valueCount = mDisplayedValues.length;
for (int i = 0; i < valueCount; i++) {
final float textWidth = mSelectorWheelPaint.measureText(mDisplayedValues[i]);
if (textWidth > maxTextWidth) {
maxTextWidth = (int) textWidth;
}
}
}
maxTextWidth += mInputText.getPaddingLeft() + mInputText.getPaddingRight();
if (mMaxWidth != maxTextWidth) {
if (maxTextWidth > mMinWidth) {
mMaxWidth = maxTextWidth;
} else {
mMaxWidth = mMinWidth;
}
invalidate();
}
|
private boolean | updateInputTextView()Updates the view of this NumberPicker. If displayValues were specified in
the string corresponding to the index specified by the current value will
be returned. Otherwise, the formatter specified in {@link #setFormatter}
will be used to format the number.
/*
* If we don't have displayed values then use the current number else
* find the correct value in the displayed values for the current
* number.
*/
String text = (mDisplayedValues == null) ? formatNumber(mValue)
: mDisplayedValues[mValue - mMinValue];
if (!TextUtils.isEmpty(text) && !text.equals(mInputText.getText().toString())) {
mInputText.setText(text);
return true;
}
return false;
|
private void | validateInputTextView(android.view.View v)
String str = String.valueOf(((TextView) v).getText());
if (TextUtils.isEmpty(str)) {
// Restore to the old value as we don't allow empty values
updateInputTextView();
} else {
// Check the new value and ensure it's in range
int current = getSelectedPos(str.toString());
setValueInternal(current, true);
}
|