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

Commit 02843213 authored by George Mount's avatar George Mount
Browse files

Fling while overscrolled: ScrollView/HorizontalScrollView

Bug: 186430321

ScrollView and HorizontalScrollView was not allowing a fling
effect while overscrolling. This adds the ability to fling
while overscrolling.

Test: new test
Test: manual ApiDemos
Change-Id: Iebd402ff0f5b6f16518ecc5403e085cb58de5976
parent 75fd8835
Loading
Loading
Loading
Loading
+29 −19
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.view.animation.AnimationUtils;
import android.view.inspector.InspectableProperty;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;

import java.util.List;

@@ -86,19 +87,23 @@ public class HorizontalScrollView extends FrameLayout {
     *
     * Even though this field is practically final, we cannot make it final because there are apps
     * setting it via reflection and they need to keep working until they target Q.
     * @hide
     */
    @NonNull
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124053130)
    private EdgeEffect mEdgeGlowLeft;
    @VisibleForTesting
    public EdgeEffect mEdgeGlowLeft;

    /**
     * Tracks the state of the bottom edge glow.
     *
     * Even though this field is practically final, we cannot make it final because there are apps
     * setting it via reflection and they need to keep working until they target Q.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124052619)
    private EdgeEffect mEdgeGlowRight;
    @VisibleForTesting
    public EdgeEffect mEdgeGlowRight;

    /**
     * Position of the last motion event.
@@ -774,11 +779,8 @@ public class HorizontalScrollView extends FrameLayout {

                    // Calling overScrollBy will call onOverScrolled, which
                    // calls onScrollChanged if applicable.
                    if (overScrollBy(deltaX, 0, mScrollX, 0, range, 0,
                            mOverscrollDistance, 0, true)) {
                        // Break our velocity if we hit a scroll barrier.
                        mVelocityTracker.clear();
                    }
                    overScrollBy(deltaX, 0, mScrollX, 0, range, 0,
                            mOverscrollDistance, 0, true);

                    if (canOverscroll && deltaX != 0f) {
                        final int pulledToX = oldX + deltaX;
@@ -1737,10 +1739,17 @@ public class HorizontalScrollView extends FrameLayout {
    public void fling(int velocityX) {
        if (getChildCount() > 0) {
            int width = getWidth() - mPaddingRight - mPaddingLeft;
            int right = getChildAt(0).getWidth();
            int right = getChildAt(0).getRight() - mPaddingLeft;

            int maxScroll = Math.max(0, right - width);

            if (mScrollX == 0 && !mEdgeGlowLeft.isFinished()) {
                mEdgeGlowLeft.onAbsorb(-velocityX);
            } else if (mScrollX == maxScroll && !mEdgeGlowRight.isFinished()) {
                mEdgeGlowRight.onAbsorb(velocityX);
            } else {
                mScroller.fling(mScrollX, mScrollY, velocityX, 0, 0,
                    Math.max(0, right - width), 0, 0, width/2, 0);
                        maxScroll, 0, 0, width / 2, 0);

                final boolean movingRight = velocityX > 0;

@@ -1755,6 +1764,7 @@ public class HorizontalScrollView extends FrameLayout {
                if (newFocused != currentFocused) {
                    newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT);
                }
            }

            postInvalidateOnAnimation();
        }
+14 −3
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.view.animation.AnimationUtils;
import android.view.inspector.InspectableProperty;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;

import java.util.List;

@@ -95,20 +96,24 @@ public class ScrollView extends FrameLayout {
     *
     * Even though this field is practically final, we cannot make it final because there are apps
     * setting it via reflection and they need to keep working until they target Q.
     * @hide
     */
    @NonNull
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768600)
    private EdgeEffect mEdgeGlowTop;
    @VisibleForTesting
    public EdgeEffect mEdgeGlowTop;

    /**
     * Tracks the state of the bottom edge glow.
     *
     * Even though this field is practically final, we cannot make it final because there are apps
     * setting it via reflection and they need to keep working until they target Q.
     * @hide
     */
    @NonNull
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769386)
    private EdgeEffect mEdgeGlowBottom;
    @VisibleForTesting
    public EdgeEffect mEdgeGlowBottom;

    /**
     * Position of the last motion event.
@@ -1791,9 +1796,15 @@ public class ScrollView extends FrameLayout {
        final boolean canFling = (mScrollY > 0 || velocityY > 0) &&
                (mScrollY < getScrollRange() || velocityY < 0);
        if (!dispatchNestedPreFling(0, velocityY)) {
            dispatchNestedFling(0, velocityY, canFling);
            final boolean consumed = dispatchNestedFling(0, velocityY, canFling);
            if (canFling) {
                fling(velocityY);
            } else if (!consumed) {
                if (!mEdgeGlowTop.isFinished()) {
                    mEdgeGlowTop.onAbsorb(-velocityY);
                } else if (!mEdgeGlowBottom.isFinished()) {
                    mEdgeGlowBottom.onAbsorb(velocityY);
                }
            }
        }
    }