diff options
author | Svetoslav Ganov <svetoslavganov@google.com> | 2012-05-10 13:00:08 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-05-10 13:00:08 -0700 |
commit | 0891a89790777e2f88f413351fafe49dda36714f (patch) | |
tree | cb2b3b6cdb63a32e3c630c9adf75a75a8faf4786 | |
parent | 822b72efd8795abe72b95d0ddd45873a5c4b77f8 (diff) | |
parent | 232dd3f335b8995cd9ab220f7b3fad77076de42b (diff) | |
download | frameworks_base-0891a89790777e2f88f413351fafe49dda36714f.zip frameworks_base-0891a89790777e2f88f413351fafe49dda36714f.tar.gz frameworks_base-0891a89790777e2f88f413351fafe49dda36714f.tar.bz2 |
Merge "Polish the NumberPicker, TimePicker, and DatePicker based on UX request." into jb-dev
-rw-r--r-- | core/java/android/widget/NumberPicker.java | 204 | ||||
-rw-r--r-- | core/res/res/layout/date_picker_holo.xml | 22 | ||||
-rw-r--r-- | core/res/res/layout/time_picker_holo.xml | 20 | ||||
-rwxr-xr-x | core/res/res/values/attrs.xml | 4 | ||||
-rw-r--r-- | core/res/res/values/styles.xml | 4 |
5 files changed, 160 insertions, 94 deletions
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 11d1ed0..6ff924b 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -133,16 +133,6 @@ public class NumberPicker extends LinearLayout { private static final int UNSCALED_DEFAULT_SELECTION_DIVIDERS_DISTANCE = 48; /** - * The default unscaled minimal distance for a swipe to be considered a fling. - */ - private static final int UNSCALED_DEFAULT_MIN_FLING_DISTANCE = 150; - - /** - * Coefficient for adjusting touch scroll distance. - */ - private static final float TOUCH_SCROLL_DECELERATION_COEFFICIENT = 2.0f; - - /** * The resource id for the default layout. */ private static final int DEFAULT_LAYOUT_RESOURCE_ID = R.layout.number_picker; @@ -233,11 +223,6 @@ public class NumberPicker extends LinearLayout { private final int mTextSize; /** - * The minimal distance for a swipe to be considered a fling. - */ - private final int mMinFlingDistance; - - /** * The height of the gap between text elements if the selector wheel. */ private int mSelectorTextGapHeight; @@ -298,6 +283,11 @@ public class NumberPicker extends LinearLayout { private final Paint mSelectorWheelPaint; /** + * The {@link Drawable} for pressed virtual (increment/decrement) buttons. + */ + private final Drawable mVirtualButtonPressedDrawable; + + /** * The height of a selector element (text + gap). */ private int mSelectorElementHeight; @@ -435,11 +425,26 @@ public class NumberPicker extends LinearLayout { private int mLastHoveredChildVirtualViewId; /** + * Whether the increment virtual button is pressed. + */ + private boolean mIncrementVirtualButtonPressed; + + /** + * Whether the decrement virtual button is pressed. + */ + private boolean mDecrementVirtualButtonPressed; + + /** * Provider to report to clients the semantic structure of this widget. */ private AccessibilityNodeProviderImpl mAccessibilityNodeProvider; /** + * Helper class for managing pressed state of the virtual buttons. + */ + private final PressedStateHelper mPressedStateHelper; + + /** * Interface to listen for changes of the current value. */ public interface OnValueChangeListener { @@ -553,12 +558,6 @@ public class NumberPicker extends LinearLayout { mSelectionDividersDistance = attributesArray.getDimensionPixelSize( R.styleable.NumberPicker_selectionDividersDistance, defSelectionDividerDistance); - final int defMinFlingDistance = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_MIN_FLING_DISTANCE, - getResources().getDisplayMetrics()); - mMinFlingDistance = attributesArray.getDimensionPixelSize( - R.styleable.NumberPicker_minFlingDistance, defMinFlingDistance); - mMinHeight = attributesArray.getDimensionPixelSize( R.styleable.NumberPicker_internalMinHeight, SIZE_UNSPECIFIED); @@ -581,8 +580,13 @@ public class NumberPicker extends LinearLayout { mComputeMaxWidth = (mMaxWidth == SIZE_UNSPECIFIED); + mVirtualButtonPressedDrawable = attributesArray.getDrawable( + R.styleable.NumberPicker_virtualButtonPressedDrawable); + attributesArray.recycle(); + mPressedStateHelper = new PressedStateHelper(); + // By default Linearlayout that we extend is not drawn. This is // its draw() method is not called but dispatchDraw() is called // directly (see ViewGroup.drawChild()). However, this class uses @@ -776,7 +780,19 @@ public class NumberPicker extends LinearLayout { mLastDownEventTime = event.getEventTime(); mIngonreMoveEvents = false; mShowSoftInputOnTap = false; - // Make sure we wupport flinging inside scrollables. + // 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); @@ -826,8 +842,7 @@ public class NumberPicker extends LinearLayout { onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); } } else { - int deltaMoveY = (int) ((currentMoveY - mLastDownOrMoveEventY) - / TOUCH_SCROLL_DECELERATION_COEFFICIENT); + int deltaMoveY = (int) ((currentMoveY - mLastDownOrMoveEventY)); scrollBy(0, deltaMoveY); invalidate(); } @@ -836,23 +851,12 @@ public class NumberPicker extends LinearLayout { 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) { - int deltaMove = (int) (event.getY() - mLastDownEventY); - int absDeltaMoveY = Math.abs(deltaMove); - if (absDeltaMoveY > mMinFlingDistance) { - fling(initialVelocity); - } else { - final int normalizedDeltaMove = - (int) (absDeltaMoveY / TOUCH_SCROLL_DECELERATION_COEFFICIENT); - if (normalizedDeltaMove < mSelectorElementHeight) { - snapToNextValue(deltaMove < 0); - } else { - snapToClosestValue(); - } - } + fling(initialVelocity); onScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); } else { int eventY = (int) event.getY(); @@ -867,8 +871,12 @@ public class NumberPicker extends LinearLayout { - 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 { @@ -1356,6 +1364,22 @@ public class NumberPicker extends LinearLayout { float x = (mRight - mLeft) / 2; float y = mCurrentScrollOffset; + // draw the virtual buttons pressed state if needed + if (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++) { @@ -1465,15 +1489,15 @@ public class NumberPicker extends LinearLayout { */ private void initializeSelectorWheelIndices() { mSelectorIndexToStringCache.clear(); - int[] selectorIdices = mSelectorIndices; + 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); } - mSelectorIndices[i] = selectorIndex; - ensureCachedScrollSelectorValue(mSelectorIndices[i]); + selectorIndices[i] = selectorIndex; + ensureCachedScrollSelectorValue(selectorIndices[i]); } } @@ -1775,6 +1799,7 @@ public class NumberPicker extends LinearLayout { if (mBeginSoftInputOnLongPressCommand != null) { removeCallbacks(mBeginSoftInputOnLongPressCommand); } + mPressedStateHelper.cancel(); } /** @@ -1910,39 +1935,80 @@ public class NumberPicker extends LinearLayout { return false; } - private void snapToNextValue(boolean increment) { - int deltaY = mCurrentScrollOffset - mInitialScrollOffset; - int amountToScroll = 0; - if (deltaY != 0) { - mPreviousScrollerY = 0; - if (deltaY > 0) { - if (increment) { - amountToScroll = - deltaY; - } else { - amountToScroll = mSelectorElementHeight - deltaY; - } - } else { - if (increment) { - amountToScroll = - mSelectorElementHeight - deltaY; - } else { - amountToScroll = - deltaY; - } + class PressedStateHelper implements Runnable { + public static final int BUTTON_INCREMENT = 1; + public static final int BUTTON_DECREMENT = 2; + + private final int MODE_PRESS = 1; + private final int MODE_TAPPED = 2; + + private int mManagedButton; + private int mMode; + + public void cancel() { + mMode = 0; + mManagedButton = 0; + NumberPicker.this.removeCallbacks(this); + if (mIncrementVirtualButtonPressed) { + mIncrementVirtualButtonPressed = false; + invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); + } + mDecrementVirtualButtonPressed = false; + if (mDecrementVirtualButtonPressed) { + invalidate(0, 0, mRight, mTopSelectionDividerTop); } - mFlingScroller.startScroll(0, 0, 0, amountToScroll, SNAP_SCROLL_DURATION); - invalidate(); } - } - private void snapToClosestValue() { - // 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; + public void buttonPressDelayed(int button) { + cancel(); + mMode = MODE_PRESS; + mManagedButton = button; + NumberPicker.this.postDelayed(this, ViewConfiguration.getTapTimeout()); + } + + public void buttonTapped(int button) { + cancel(); + mMode = MODE_TAPPED; + mManagedButton = button; + NumberPicker.this.post(this); + } + + @Override + public void run() { + switch (mMode) { + case MODE_PRESS: { + switch (mManagedButton) { + case BUTTON_INCREMENT: { + mIncrementVirtualButtonPressed = true; + invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); + } break; + case BUTTON_DECREMENT: { + mDecrementVirtualButtonPressed = true; + invalidate(0, 0, mRight, mTopSelectionDividerTop); + } + } + } break; + case MODE_TAPPED: { + switch (mManagedButton) { + case BUTTON_INCREMENT: { + if (!mIncrementVirtualButtonPressed) { + NumberPicker.this.postDelayed(this, + ViewConfiguration.getPressedStateDuration()); + } + mIncrementVirtualButtonPressed ^= true; + invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom); + } break; + case BUTTON_DECREMENT: { + if (!mDecrementVirtualButtonPressed) { + NumberPicker.this.postDelayed(this, + ViewConfiguration.getPressedStateDuration()); + } + mDecrementVirtualButtonPressed ^= true; + invalidate(0, 0, mRight, mTopSelectionDividerTop); + } + } + } break; } - mFlingScroller.startScroll(0, 0, 0, deltaY, SNAP_SCROLL_DURATION); - invalidate(); } } diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_holo.xml index 122a61a..8008682 100644 --- a/core/res/res/layout/date_picker_holo.xml +++ b/core/res/res/layout/date_picker_holo.xml @@ -41,10 +41,10 @@ android:id="@+id/month" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" - android:layout_marginLeft="16dip" - android:layout_marginRight="16dip" + android:layout_marginTop="16dip" + android:layout_marginBottom="16dip" + android:layout_marginLeft="8dip" + android:layout_marginRight="8dip" android:focusable="true" android:focusableInTouchMode="true" /> @@ -54,10 +54,10 @@ android:id="@+id/day" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" - android:layout_marginLeft="16dip" - android:layout_marginRight="16dip" + android:layout_marginTop="16dip" + android:layout_marginBottom="16dip" + android:layout_marginLeft="8dip" + android:layout_marginRight="8dip" android:focusable="true" android:focusableInTouchMode="true" /> @@ -67,9 +67,9 @@ android:id="@+id/year" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" - android:layout_marginLeft="16dip" + android:layout_marginTop="16dip" + android:layout_marginBottom="16dip" + android:layout_marginLeft="8dip" android:layout_marginRight="16dip" android:focusable="true" android:focusableInTouchMode="true" diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml index 24b6194..91e66bc 100644 --- a/core/res/res/layout/time_picker_holo.xml +++ b/core/res/res/layout/time_picker_holo.xml @@ -30,10 +30,10 @@ android:id="@+id/hour" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" + android:layout_marginTop="16dip" + android:layout_marginBottom="16dip" android:layout_marginLeft="16dip" - android:layout_marginRight="14dip" + android:layout_marginRight="6dip" android:focusable="true" android:focusableInTouchMode="true" /> @@ -51,10 +51,10 @@ android:id="@+id/minute" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" - android:layout_marginLeft="14dip" - android:layout_marginRight="16dip" + android:layout_marginTop="16dip" + android:layout_marginBottom="16dip" + android:layout_marginLeft="6dip" + android:layout_marginRight="8dip" android:focusable="true" android:focusableInTouchMode="true" /> @@ -64,9 +64,9 @@ android:id="@+id/amPm" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dip" - android:layout_marginBottom="10dip" - android:layout_marginLeft="16dip" + android:layout_marginTop="16dip" + android:layout_marginBottom="16dip" + android:layout_marginLeft="8dip" android:layout_marginRight="16dip" android:focusable="true" android:focusableInTouchMode="true" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index ad1dff5..a4d9e14 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3685,8 +3685,8 @@ <attr name="internalMaxWidth" format="dimension" /> <!-- @hide The layout of the number picker. --> <attr name="internalLayout" /> - <!-- @hide The minimal move distance of a swipe to be considered a fling. --> - <attr name="minFlingDistance" format="dimension" /> + <!-- @hide The drawable for pressed virtual (increment/decrement) buttons. --> + <attr name="virtualButtonPressedDrawable" format="reference"/> </declare-styleable> <declare-styleable name="TimePicker"> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 18ee2f8..2b34dab 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1649,9 +1649,9 @@ please see styles_device_defaults.xml. <item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item> <item name="android:selectionDividerHeight">2dip</item> <item name="android:selectionDividersDistance">48dip</item> - <item name="android:internalMinWidth">48dip</item> + <item name="android:internalMinWidth">64dip</item> <item name="android:internalMaxHeight">180dip</item> - <item name="android:minFlingDistance">150dip</item> + <item name="virtualButtonPressedDrawable">?android:attr/selectableItemBackground</item> </style> <style name="Widget.Holo.TimePicker" parent="Widget.TimePicker"> |