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

Commit c501db9f authored by Adam Powell's avatar Adam Powell
Browse files

New, inkier EdgeEffect visual style

Remove the two-part gradient and edge glow and replace it with a
circular ink-like style instead. This now follows the theme color
palette so that it can be more in tune with the app's overall visual
design.

Add API to EdgeEffect to specify a horizontal displacement for the
effect. This lets the larger middle section follow relevant touch
points.

Fix a bug that caused EdgeEffect pulls to stutter in ListView/GridView
as a result of some annoying state-fluttering.

Change-Id: Ief144b06bd9d3dbe85d3154585a703fa552b0808
parent a5008742
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -34886,9 +34886,11 @@ package android.widget {
    ctor public EdgeEffect(android.content.Context);
    method public boolean draw(android.graphics.Canvas);
    method public void finish();
    method public int getMaxHeight();
    method public boolean isFinished();
    method public void onAbsorb(int);
    method public void onPull(float);
    method public void onPull(float, float);
    method public void onRelease();
    method public void setSize(int, int);
  }
+41 −30
Original line number Diff line number Diff line
@@ -3267,7 +3267,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        }
    }

    private boolean startScrollIfNeeded(int y, MotionEvent vtev) {
    private boolean startScrollIfNeeded(int x, int y, MotionEvent vtev) {
        // Check if we have moved far enough that it looks more like a
        // scroll than a tap
        final int deltaY = y - mMotionY;
@@ -3296,14 +3296,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            if (parent != null) {
                parent.requestDisallowInterceptTouchEvent(true);
            }
            scrollIfNeeded(y, vtev);
            scrollIfNeeded(x, y, vtev);
            return true;
        }

        return false;
    }

    private void scrollIfNeeded(int y, MotionEvent vtev) {
    private void scrollIfNeeded(int x, int y, MotionEvent vtev) {
        int rawDeltaY = y - mMotionY;
        if (dispatchNestedPreScroll(0, rawDeltaY, mScrollConsumed, mScrollOffset)) {
            rawDeltaY -= mScrollConsumed[1];
@@ -3384,33 +3384,39 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                                vtev.offsetLocation(0, mScrollOffset[1]);
                            }
                        } else {
                            overScrollBy(0, overscroll, 0, mScrollY, 0, 0,
                                    0, mOverscrollDistance, true);
                            if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) {
                                // Don't allow overfling if we're at the edge.
                                if (mVelocityTracker != null) {
                            final boolean atOverscrollEdge = overScrollBy(0, overscroll,
                                    0, mScrollY, 0, 0, 0, mOverscrollDistance, true);

                            if (atOverscrollEdge && mVelocityTracker != null) {
                                // Don't allow overfling if we're at the edge
                                mVelocityTracker.clear();
                            }
                            }

                            final int overscrollMode = getOverScrollMode();
                            if (overscrollMode == OVER_SCROLL_ALWAYS ||
                                    (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
                                            !contentFits())) {
                                if (!atOverscrollEdge) {
                                    mDirection = 0; // Reset when entering overscroll.
                                    mTouchMode = TOUCH_MODE_OVERSCROLL;
                                if (deltaY > 0) {
                                    mEdgeGlowTop.onPull((float) overscroll / getHeight());
                                }
                                if (incrementalDeltaY > 0) {
                                    mEdgeGlowTop.onPull((float) overscroll / getHeight(),
                                            (float) x / getWidth());
                                    if (!mEdgeGlowBottom.isFinished()) {
                                        mEdgeGlowBottom.onRelease();
                                    }
                                    invalidate(mEdgeGlowTop.getBounds(false));
                                } else if (deltaY < 0) {
                                    mEdgeGlowBottom.onPull((float) overscroll / getHeight());
                                    invalidate(0, 0, getWidth(),
                                            mEdgeGlowTop.getMaxHeight() + getPaddingTop());
                                } else if (incrementalDeltaY < 0) {
                                    mEdgeGlowBottom.onPull((float) overscroll / getHeight(),
                                            1.f - (float) x / getWidth());
                                    if (!mEdgeGlowTop.isFinished()) {
                                        mEdgeGlowTop.onRelease();
                                    }
                                    invalidate(mEdgeGlowBottom.getBounds(true));
                                    invalidate(0, getHeight() - getPaddingBottom() -
                                            mEdgeGlowBottom.getMaxHeight(), getWidth(),
                                            getHeight());
                                }
                            }
                        }
@@ -3445,17 +3451,22 @@ 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.onPull((float) overScrollDistance / getHeight(),
                                    (float) x / getWidth());
                            if (!mEdgeGlowBottom.isFinished()) {
                                mEdgeGlowBottom.onRelease();
                            }
                            invalidate(mEdgeGlowTop.getBounds(false));
                            invalidate(0, 0, getWidth(),
                                    mEdgeGlowTop.getMaxHeight() + getPaddingTop());
                        } else if (rawDeltaY < 0) {
                            mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight());
                            mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight(),
                                    1.f - (float) x / getWidth());
                            if (!mEdgeGlowTop.isFinished()) {
                                mEdgeGlowTop.onRelease();
                            }
                            invalidate(mEdgeGlowBottom.getBounds(true));
                            invalidate(0, getHeight() - getPaddingBottom() -
                                    mEdgeGlowBottom.getMaxHeight(), getWidth(),
                                    getHeight());
                        }
                    }
                }
@@ -3703,7 +3714,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
            case TOUCH_MODE_DONE_WAITING:
                // Check if we have moved far enough that it looks more like a
                // scroll than a tap. If so, we'll enter scrolling mode.
                if (startScrollIfNeeded(y, vtev)) {
                if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, vtev)) {
                    break;
                }
                // Otherwise, check containment within list bounds. If we're
@@ -3723,7 +3734,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                break;
            case TOUCH_MODE_SCROLL:
            case TOUCH_MODE_OVERSCROLL:
                scrollIfNeeded(y, vtev);
                scrollIfNeeded((int) ev.getX(pointerIndex), y, vtev);
                break;
        }
    }
@@ -4022,8 +4033,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                canvas.translate(leftPadding, edgeY);
                mEdgeGlowTop.setSize(width, getHeight());
                if (mEdgeGlowTop.draw(canvas)) {
                    mEdgeGlowTop.setPosition(leftPadding, edgeY);
                    invalidate(mEdgeGlowTop.getBounds(false));
                    invalidate(0, 0, getWidth(),
                            mEdgeGlowTop.getMaxHeight() + getPaddingTop());
                }
                canvas.restoreToCount(restoreCount);
            }
@@ -4040,9 +4051,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                canvas.rotate(180, width, 0);
                mEdgeGlowBottom.setSize(width, height);
                if (mEdgeGlowBottom.draw(canvas)) {
                    // Account for the rotation
                    mEdgeGlowBottom.setPosition(edgeX + width, edgeY);
                    invalidate(mEdgeGlowBottom.getBounds(true));
                    invalidate(0, getHeight() - getPaddingBottom() -
                            mEdgeGlowBottom.getMaxHeight(), getWidth(),
                            getHeight());
                }
                canvas.restoreToCount(restoreCount);
            }
@@ -4161,7 +4172,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                final int y = (int) ev.getY(pointerIndex);
                initVelocityTrackerIfNotExists();
                mVelocityTracker.addMovement(ev);
                if (startScrollIfNeeded(y, null)) {
                if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, null)) {
                    return true;
                }
                break;
+85 −136
Original line number Diff line number Diff line
@@ -16,7 +16,14 @@

package android.widget;

import android.content.res.TypedArray;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.util.Log;
import com.android.internal.R;

import android.content.Context;
@@ -59,12 +66,10 @@ public class EdgeEffect {
    private static final int PULL_DECAY_TIME = 1000;

    private static final float MAX_ALPHA = 1.f;
    private static final float HELD_EDGE_SCALE_Y = 0.5f;

    private static final float MAX_GLOW_HEIGHT = 4.f;
    private static final float MAX_GLOW_HEIGHT = 1.5f;

    private static final float PULL_GLOW_BEGIN = 1.f;
    private static final float PULL_EDGE_BEGIN = 0.6f;
    private static final float PULL_GLOW_BEGIN = 0.f;

    // Minimum velocity that will be absorbed
    private static final int MIN_VELOCITY = 100;
@@ -73,24 +78,11 @@ public class EdgeEffect {

    private static final float EPSILON = 0.001f;

    private final Drawable mEdge;
    private final Drawable mGlow;
    private int mWidth;
    private int mHeight;
    private int mX;
    private int mY;
    private static final int MIN_WIDTH = 300;
    private final int mMinWidth;

    private float mEdgeAlpha;
    private float mEdgeScaleY;
    private static final float SIN_45 = (float) Math.sin(Math.PI / 4);

    private float mGlowAlpha;
    private float mGlowScaleY;

    private float mEdgeAlphaStart;
    private float mEdgeAlphaFinish;
    private float mEdgeScaleYStart;
    private float mEdgeScaleYFinish;
    private float mGlowAlphaStart;
    private float mGlowAlphaFinish;
    private float mGlowScaleYStart;
@@ -107,16 +99,11 @@ public class EdgeEffect {
    private static final int STATE_RECEDE = 3;
    private static final int STATE_PULL_DECAY = 4;

    // How much dragging should effect the height of the edge image.
    // Number determined by user testing.
    private static final int PULL_DISTANCE_EDGE_FACTOR = 7;

    // How much dragging should effect the height of the glow image.
    // Number determined by user testing.
    private static final int PULL_DISTANCE_GLOW_FACTOR = 7;
    private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f;

    private static final int VELOCITY_EDGE_FACTOR = 8;
    private static final int VELOCITY_GLOW_FACTOR = 12;

    private int mState = STATE_IDLE;
@@ -124,30 +111,26 @@ public class EdgeEffect {
    private float mPullDistance;
    
    private final Rect mBounds = new Rect();

    private final int mEdgeHeight;
    private final int mGlowHeight;
    private final int mGlowWidth;
    private final int mMaxEffectHeight;
    private final RectF mArcRect = new RectF();
    private final Paint mPaint = new Paint();
    private float mRadius;
    private float mDisplacement = 0.5f;
    private float mTargetDisplacement = 0.5f;

    /**
     * Construct a new EdgeEffect with a theme appropriate for the provided context.
     * @param context Context used to provide theming and resource information for the EdgeEffect
     */
    public EdgeEffect(Context context) {
        final Resources res = context.getResources();
        mEdge = context.getDrawable(R.drawable.overscroll_edge);
        mGlow = context.getDrawable(R.drawable.overscroll_glow);

        mEdgeHeight = mEdge.getIntrinsicHeight();
        mGlowHeight = mGlow.getIntrinsicHeight();
        mGlowWidth = mGlow.getIntrinsicWidth();

        mMaxEffectHeight = (int) (Math.min(
                mGlowHeight * MAX_GLOW_HEIGHT * mGlowHeight / mGlowWidth * 0.6f,
                mGlowHeight * MAX_GLOW_HEIGHT) + 0.5f);

        mMinWidth = (int) (res.getDisplayMetrics().density * MIN_WIDTH + 0.5f);
        mPaint.setAntiAlias(true);
        final TypedArray a = context.obtainStyledAttributes(
                com.android.internal.R.styleable.EdgeEffect);
        final int themeColor = a.getColor(
                com.android.internal.R.styleable.EdgeEffect_colorPrimaryLight, 0xff666666);
        a.recycle();
        mPaint.setColor((themeColor & 0xffffff) | 0x66000000);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
        mInterpolator = new DecelerateInterpolator();
    }

@@ -158,20 +141,12 @@ public class EdgeEffect {
     * @param height Effect height in pixels
     */
    public void setSize(int width, int height) {
        mWidth = width;
        mHeight = height;
    }
        final float r = width * 0.5f / SIN_45;
        final float y = SIN_45 * r;
        final float h = r - y;
        mRadius = r;

    /**
     * Set the position of this edge effect in pixels. This position is
     * only used by {@link #getBounds(boolean)}.
     * 
     * @param x The position of the edge effect on the X axis
     * @param y The position of the edge effect on the Y axis
     */
    void setPosition(int x, int y) {
        mX = x;
        mY = y;
        mBounds.set(mBounds.left, mBounds.top, width, (int) Math.min(height, h));
    }

    /**
@@ -199,17 +174,38 @@ public class EdgeEffect {
     * The host view should always {@link android.view.View#invalidate()} after this
     * and draw the results accordingly.
     *
     * <p>Views using EdgeEffect should favor {@link #onPull(float, float)} when the displacement
     * of the pull point is known.</p>
     *
     * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to
     *                      1.f (full length of the view) or negative values to express change
     *                      back toward the edge reached to initiate the effect.
     */
    public void onPull(float deltaDistance) {
        onPull(deltaDistance, 0.5f);
    }

    /**
     * A view should call this when content is pulled away from an edge by the user.
     * This will update the state of the current visual effect and its associated animation.
     * The host view should always {@link android.view.View#invalidate()} after this
     * and draw the results accordingly.
     *
     * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to
     *                      1.f (full length of the view) or negative values to express change
     *                      back toward the edge reached to initiate the effect.
     * @param displacement The displacement from the starting side of the effect of the point
     *                     initiating the pull. In the case of touch this is the finger position.
     *                     Values may be from 0-1.
     */
    public void onPull(float deltaDistance, float displacement) {
        final long now = AnimationUtils.currentAnimationTimeMillis();
        mTargetDisplacement = displacement;
        if (mState == STATE_PULL_DECAY && now - mStartTime < mDuration) {
            return;
        }
        if (mState != STATE_PULL) {
            mGlowScaleY = PULL_GLOW_BEGIN;
            mGlowScaleY = Math.max(PULL_GLOW_BEGIN, mGlowScaleY);
        }
        mState = STATE_PULL;

@@ -217,11 +213,6 @@ public class EdgeEffect {
        mDuration = PULL_TIME;

        mPullDistance += deltaDistance;
        float distance = Math.abs(mPullDistance);

        mEdgeAlpha = mEdgeAlphaStart = Math.max(PULL_EDGE_BEGIN, Math.min(distance, MAX_ALPHA));
        mEdgeScaleY = mEdgeScaleYStart = Math.max(
                HELD_EDGE_SCALE_Y, Math.min(distance * PULL_DISTANCE_EDGE_FACTOR, 1.f));

        mGlowAlpha = mGlowAlphaStart = Math.min(MAX_ALPHA,
                mGlowAlpha +
@@ -239,8 +230,6 @@ public class EdgeEffect {
        mGlowScaleY = mGlowScaleYStart = Math.min(MAX_GLOW_HEIGHT, Math.max(
                0, mGlowScaleY + glowChange * PULL_DISTANCE_GLOW_FACTOR));

        mEdgeAlphaFinish = mEdgeAlpha;
        mEdgeScaleYFinish = mEdgeScaleY;
        mGlowAlphaFinish = mGlowAlpha;
        mGlowScaleYFinish = mGlowScaleY;
    }
@@ -259,13 +248,9 @@ public class EdgeEffect {
        }

        mState = STATE_RECEDE;
        mEdgeAlphaStart = mEdgeAlpha;
        mEdgeScaleYStart = mEdgeScaleY;
        mGlowAlphaStart = mGlowAlpha;
        mGlowScaleYStart = mGlowScaleY;

        mEdgeAlphaFinish = 0.f;
        mEdgeScaleYFinish = 0.f;
        mGlowAlphaFinish = 0.f;
        mGlowScaleYFinish = 0.f;

@@ -290,30 +275,21 @@ public class EdgeEffect {
        mStartTime = AnimationUtils.currentAnimationTimeMillis();
        mDuration = 0.15f + (velocity * 0.02f);

        // The edge should always be at least partially visible, regardless
        // of velocity.
        mEdgeAlphaStart = 0.f;
        mEdgeScaleY = mEdgeScaleYStart = 0.f;
        // The glow depends more on the velocity, and therefore starts out
        // nearly invisible.
        mGlowAlphaStart = 0.3f;
        mGlowScaleYStart = 0.f;
        mGlowScaleYStart = Math.max(mGlowScaleY, 0.f);

        // Factor the velocity by 8. Testing on device shows this works best to
        // reflect the strength of the user's scrolling.
        mEdgeAlphaFinish = Math.max(0, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1));
        // Edge should never get larger than the size of its asset.
        mEdgeScaleYFinish = Math.max(
                HELD_EDGE_SCALE_Y, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1.f));

        // Growth for the size of the glow should be quadratic to properly
        // respond
        // to a user's scrolling speed. The faster the scrolling speed, the more
        // intense the effect should be for both the size and the saturation.
        mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f);
        mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f) / 2, 1.f);
        // Alpha should change for the glow as well as size.
        mGlowAlphaFinish = Math.max(
                mGlowAlphaStart, Math.min(velocity * VELOCITY_GLOW_FACTOR * .00001f, MAX_ALPHA));
        mTargetDisplacement = 0.5f;
    }


@@ -330,52 +306,42 @@ public class EdgeEffect {
    public boolean draw(Canvas canvas) {
        update();

        mGlow.setAlpha((int) (Math.max(0, Math.min(mGlowAlpha, 1)) * 255));

        int glowBottom = (int) Math.min(
                mGlowHeight * mGlowScaleY * mGlowHeight / mGlowWidth * 0.6f,
                mGlowHeight * MAX_GLOW_HEIGHT);
        if (mWidth < mMinWidth) {
            // Center the glow and clip it.
            int glowLeft = (mWidth - mMinWidth)/2;
            mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom);
        } else {
            // Stretch the glow to fit.
            mGlow.setBounds(0, 0, mWidth, glowBottom);
        }

        mGlow.draw(canvas);
        final int count = canvas.save();

        mEdge.setAlpha((int) (Math.max(0, Math.min(mEdgeAlpha, 1)) * 255));
        final float y = mBounds.height();
        final float centerY = y - mRadius;
        final float centerX = mBounds.centerX();
        mArcRect.set(centerX - mRadius, centerY - mRadius, centerX + mRadius, centerY + mRadius);
        canvas.scale(1.f, Math.min(mGlowScaleY, 1.f), centerX, 0);

        int edgeBottom = (int) (mEdgeHeight * mEdgeScaleY);
        if (mWidth < mMinWidth) {
            // Center the edge and clip it.
            int edgeLeft = (mWidth - mMinWidth)/2;
            mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom);
        } else {
            // Stretch the edge to fit.
            mEdge.setBounds(0, 0, mWidth, edgeBottom);
        final float displacement = Math.max(0, Math.min(mDisplacement, 1.f)) - 0.5f;
        float translateX = mBounds.width() * displacement;
        float translateY = 0;
        if (mGlowScaleY > 1.f) {
            translateY = (mGlowScaleY - 1.f) * mBounds.height();
        }
        mEdge.draw(canvas);

        if (mState == STATE_RECEDE && glowBottom == 0 && edgeBottom == 0) {
        canvas.clipRect(Float.MIN_VALUE, mBounds.top,
                Float.MAX_VALUE, Float.MAX_VALUE);
        canvas.translate(translateX, translateY);
        canvas.drawArc(mArcRect, 0, 180, true, mPaint);
        canvas.restoreToCount(count);

        boolean oneLastFrame = false;
        if (mState == STATE_RECEDE && mGlowScaleY == 0) {
            mState = STATE_IDLE;
            oneLastFrame = true;
        }

        return mState != STATE_IDLE;
        return mState != STATE_IDLE || oneLastFrame;
    }

    /**
     * Returns the bounds of the edge effect.
     * 
     * @hide
     * Return the maximum height that the edge effect will be drawn at given the original
     * {@link #setSize(int, int) input size}.
     * @return The maximum height of the edge effect
     */
    public Rect getBounds(boolean reverse) {
        mBounds.set(0, 0, mWidth, mMaxEffectHeight);
        mBounds.offset(mX, mY - (reverse ? mMaxEffectHeight : 0));

        return mBounds;
    public int getMaxHeight() {
        return (int) (mBounds.height() * MAX_GLOW_HEIGHT + 0.5f);
    }

    private void update() {
@@ -384,10 +350,9 @@ public class EdgeEffect {

        final float interp = mInterpolator.getInterpolation(t);

        mEdgeAlpha = mEdgeAlphaStart + (mEdgeAlphaFinish - mEdgeAlphaStart) * interp;
        mEdgeScaleY = mEdgeScaleYStart + (mEdgeScaleYFinish - mEdgeScaleYStart) * interp;
        mGlowAlpha = mGlowAlphaStart + (mGlowAlphaFinish - mGlowAlphaStart) * interp;
        mGlowScaleY = mGlowScaleYStart + (mGlowScaleYFinish - mGlowScaleYStart) * interp;
        mDisplacement = (mDisplacement + mTargetDisplacement) / 2;

        if (t >= 1.f - EPSILON) {
            switch (mState) {
@@ -396,14 +361,10 @@ public class EdgeEffect {
                    mStartTime = AnimationUtils.currentAnimationTimeMillis();
                    mDuration = RECEDE_TIME;

                    mEdgeAlphaStart = mEdgeAlpha;
                    mEdgeScaleYStart = mEdgeScaleY;
                    mGlowAlphaStart = mGlowAlpha;
                    mGlowScaleYStart = mGlowScaleY;

                    // After absorb, the glow and edge should fade to nothing.
                    mEdgeAlphaFinish = 0.f;
                    mEdgeScaleYFinish = 0.f;
                    // After absorb, the glow should fade to nothing.
                    mGlowAlphaFinish = 0.f;
                    mGlowScaleYFinish = 0.f;
                    break;
@@ -412,26 +373,14 @@ public class EdgeEffect {
                    mStartTime = AnimationUtils.currentAnimationTimeMillis();
                    mDuration = PULL_DECAY_TIME;

                    mEdgeAlphaStart = mEdgeAlpha;
                    mEdgeScaleYStart = mEdgeScaleY;
                    mGlowAlphaStart = mGlowAlpha;
                    mGlowScaleYStart = mGlowScaleY;

                    // After pull, the glow and edge should fade to nothing.
                    mEdgeAlphaFinish = 0.f;
                    mEdgeScaleYFinish = 0.f;
                    // After pull, the glow should fade to nothing.
                    mGlowAlphaFinish = 0.f;
                    mGlowScaleYFinish = 0.f;
                    break;
                case STATE_PULL_DECAY:
                    // When receding, we want edge to decrease more slowly
                    // than the glow.
                    float factor = mGlowScaleYFinish != 0 ? 1
                            / (mGlowScaleYFinish * mGlowScaleYFinish)
                            : Float.MAX_VALUE;
                    mEdgeScaleY = mEdgeScaleYStart +
                        (mEdgeScaleYFinish - mEdgeScaleYStart) *
                            interp * factor;
                    mState = STATE_RECEDE;
                    break;
                case STATE_RECEDE:
+4 −2
Original line number Diff line number Diff line
@@ -616,12 +616,14 @@ public class HorizontalScrollView extends FrameLayout {
                    if (canOverscroll) {
                        final int pulledToX = oldX + deltaX;
                        if (pulledToX < 0) {
                            mEdgeGlowLeft.onPull((float) deltaX / getWidth());
                            mEdgeGlowLeft.onPull((float) deltaX / getWidth(),
                                    1.f - ev.getY(activePointerIndex) / getHeight());
                            if (!mEdgeGlowRight.isFinished()) {
                                mEdgeGlowRight.onRelease();
                            }
                        } else if (pulledToX > range) {
                            mEdgeGlowRight.onPull((float) deltaX / getWidth());
                            mEdgeGlowRight.onPull((float) deltaX / getWidth(),
                                    ev.getY(activePointerIndex) / getHeight());
                            if (!mEdgeGlowLeft.isFinished()) {
                                mEdgeGlowLeft.onRelease();
                            }
+4 −2

File changed.

Preview size limit exceeded, changes collapsed.

Loading