Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0891a897 authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android (Google) Code Review
Browse files

Merge "Polish the NumberPicker, TimePicker, and DatePicker based on UX request." into jb-dev

parents 822b72ef 232dd3f3
Loading
Loading
Loading
Loading
+135 −69
Original line number Diff line number Diff line
@@ -132,16 +132,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.
     */
@@ -232,11 +222,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.
     */
@@ -297,6 +282,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).
     */
@@ -434,11 +424,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.
     */
@@ -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();
                        }
                    }
                    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;
    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);
            }
            } else {
                if (increment) {
                    amountToScroll = - mSelectorElementHeight - deltaY;
                } else {
                    amountToScroll = - deltaY;
            mDecrementVirtualButtonPressed = false;
            if (mDecrementVirtualButtonPressed) {
                invalidate(0, 0, mRight, mTopSelectionDividerTop);
            }
        }
            mFlingScroller.startScroll(0, 0, 0, amountToScroll, SNAP_SCROLL_DURATION);
            invalidate();

        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);
        }

    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;
        @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();
        }
    }

+11 −11
Original line number Diff line number Diff line
@@ -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"
+10 −10
Original line number Diff line number Diff line
@@ -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"
+2 −2
Original line number Diff line number Diff line
@@ -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">
+2 −2
Original line number Diff line number Diff line
@@ -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">