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

Commit d90f9858 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "ListView implementation for stretch overscroll." into sc-dev

parents 42263384 3cdfc896
Loading
Loading
Loading
Loading
+129 −65
Original line number Diff line number Diff line
@@ -715,7 +715,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     */
    @NonNull
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769408)
    private EdgeEffect mEdgeGlowTop = new EdgeEffect(mContext);
    private EdgeEffect mEdgeGlowTop;

    /**
     * Tracks the state of the bottom edge glow.
@@ -725,7 +725,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     */
    @NonNull
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768444)
    private EdgeEffect mEdgeGlowBottom = new EdgeEffect(mContext);
    private EdgeEffect mEdgeGlowBottom;

    /**
     * An estimate of how many pixels are between the top of the list and
@@ -847,6 +847,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

    public AbsListView(Context context) {
        super(context);
        mEdgeGlowBottom = new EdgeEffect(context);
        mEdgeGlowTop = new EdgeEffect(context);
        initAbsListView();

        mOwnerThread = Thread.currentThread();
@@ -867,6 +869,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

    public AbsListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mEdgeGlowBottom = new EdgeEffect(context, attrs);
        mEdgeGlowTop = new EdgeEffect(context, attrs);
        initAbsListView();

        mOwnerThread = Thread.currentThread();
@@ -3584,6 +3588,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                mLastY != Integer.MIN_VALUE ? y - mLastY + scrollConsumedCorrection : deltaY;
        int lastYCorrection = 0;

        // First allow releasing existing overscroll effect:
        incrementalDeltaY = releaseGlow(incrementalDeltaY, x);

        if (mTouchMode == TOUCH_MODE_SCROLL) {
            if (PROFILE_SCROLLING) {
                if (!mScrollProfilingStarted) {
@@ -3666,14 +3673,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                                    mTouchMode = TOUCH_MODE_OVERSCROLL;
                                }
                                if (incrementalDeltaY > 0) {
                                    mEdgeGlowTop.onPull((float) -overscroll / getHeight(),
                                    mEdgeGlowTop.onPullDistance((float) -overscroll / getHeight(),
                                            (float) x / getWidth());
                                    if (!mEdgeGlowBottom.isFinished()) {
                                        mEdgeGlowBottom.onRelease();
                                    }
                                    invalidateTopGlow();
                                } else if (incrementalDeltaY < 0) {
                                    mEdgeGlowBottom.onPull((float) overscroll / getHeight(),
                                    mEdgeGlowBottom.onPullDistance((float) overscroll / getHeight(),
                                            1.f - (float) x / getWidth());
                                    if (!mEdgeGlowTop.isFinished()) {
                                        mEdgeGlowTop.onRelease();
@@ -3713,14 +3720,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                            (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
                                    !contentFits())) {
                        if (rawDeltaY > 0) {
                            mEdgeGlowTop.onPull((float) overScrollDistance / getHeight(),
                            mEdgeGlowTop.onPullDistance((float) overScrollDistance / getHeight(),
                                    (float) x / getWidth());
                            if (!mEdgeGlowBottom.isFinished()) {
                                mEdgeGlowBottom.onRelease();
                            }
                            invalidateTopGlow();
                        } else if (rawDeltaY < 0) {
                            mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight(),
                            mEdgeGlowBottom.onPullDistance(
                                    (float) -overScrollDistance / getHeight(),
                                    1.f - (float) x / getWidth());
                            if (!mEdgeGlowTop.isFinished()) {
                                mEdgeGlowTop.onRelease();
@@ -3757,6 +3765,44 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        }
    }

    /**
     * If the edge glow is currently active, this consumes part or all of deltaY
     * on the edge glow.
     *
     * @param deltaY The pointer motion, in pixels, in the vertical direction, positive
     *                         for moving down and negative for moving up.
     * @param x The horizontal position of the pointer.
     * @return The remainder of <code>deltaY</code> that has not been consumed by the
     * edge glow.
     */
    private int releaseGlow(int deltaY, int x) {
        // First allow releasing existing overscroll effect:
        float consumed = 0;
        if (mEdgeGlowTop.getDistance() != 0) {
            consumed = mEdgeGlowTop.onPullDistance((float) deltaY / getHeight(),
                    (float) x / getWidth());
            if (consumed != 0f) {
                invalidateTopGlow();
            }
        } else if (mEdgeGlowBottom.getDistance() != 0) {
            consumed = -mEdgeGlowBottom.onPullDistance((float) -deltaY / getHeight(),
                    1f - (float) x / getWidth());
            if (consumed != 0f) {
                invalidateBottomGlow();
            }
        }
        int pixelsConsumed = Math.round(consumed * getHeight());
        return deltaY - pixelsConsumed;
    }

    /**
     * @return <code>true</code> if either the top or bottom edge glow is currently active or
     * <code>false</code> if it has no value to release.
     */
    private boolean isGlowActive() {
        return mEdgeGlowBottom.getDistance() != 0 || mEdgeGlowTop.getDistance() != 0;
    }

    private void invalidateTopGlow() {
        if (!shouldDisplayEdgeEffects()) {
            return;
@@ -3926,7 +3972,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te

        if (mTouchMode == TOUCH_MODE_OVERFLING) {
            // Stopped the fling. It is a scroll.
            if (mFlingRunnable != null) {
                mFlingRunnable.endFling();
            }
            if (mPositionScroller != null) {
                mPositionScroller.stop();
            }
@@ -3936,6 +3984,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            mLastY = mMotionY;
            mMotionCorrection = 0;
            mDirection = 0;
            stopEdgeGlowRecede(ev.getX());
        } else {
            final int x = (int) ev.getX();
            final int y = (int) ev.getY();
@@ -3948,7 +3997,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    mTouchMode = TOUCH_MODE_SCROLL;
                    mMotionCorrection = 0;
                    motionPosition = findMotionRow(y);
                    if (mFlingRunnable != null) {
                        mFlingRunnable.flywheelTouch();
                    }
                    stopEdgeGlowRecede(x);
                } else if ((motionPosition >= 0) && getAdapter().isEnabled(motionPosition)) {
                    // User clicked on an actual view (and was not stopping a
                    // fling). It might be a click or a scroll. Assume it is a
@@ -3984,6 +4036,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        }
    }

    private void stopEdgeGlowRecede(float x) {
        if (mEdgeGlowTop.getDistance() != 0) {
            mEdgeGlowTop.onPullDistance(0, x / getWidth());
        }
        if (mEdgeGlowBottom.getDistance() != 0) {
            mEdgeGlowBottom.onPullDistance(0, x / getWidth());
        }
    }

    private void onTouchMove(MotionEvent ev, MotionEvent vtev) {
        if (mHasPerformedLongPress) {
            // Consume all move events following a successful long press.
@@ -4501,7 +4562,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                mActivePointerId = ev.getPointerId(0);

                int motionPosition = findMotionRow(y);
            if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
                if (isGlowActive()) {
                    // Pressed during edge effect, so this is considered the same as a fling catch.
                    mTouchMode = TOUCH_MODE_FLING;
                } else if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
                    // User clicked on an actual view (and was not stopping a fling).
                    // Remember where the motion event started
                    v = getChildAt(motionPosition - mFirstPosition);