diff options
Diffstat (limited to 'core/java/android/widget/ScrollView.java')
| -rw-r--r-- | core/java/android/widget/ScrollView.java | 57 |
1 files changed, 46 insertions, 11 deletions
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index f3de9828c4aa..693b13bbf224 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -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 = new EdgeEffect(getContext()); + @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 = new EdgeEffect(getContext()); + @VisibleForTesting + public EdgeEffect mEdgeGlowBottom; /** * Position of the last motion event. @@ -213,6 +218,8 @@ public class ScrollView extends FrameLayout { public ScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + mEdgeGlowTop = new EdgeEffect(context, attrs); + mEdgeGlowBottom = new EdgeEffect(context, attrs); initScrollView(); final TypedArray a = context.obtainStyledAttributes( @@ -340,7 +347,6 @@ public class ScrollView extends FrameLayout { return (int) (MAX_SCROLL_FACTOR * (mBottom - mTop)); } - private void initScrollView() { mScroller = new OverScroller(getContext()); setFocusable(true); @@ -679,7 +685,15 @@ public class ScrollView extends FrameLayout { * isFinished() is correct. */ mScroller.computeScrollOffset(); - mIsBeingDragged = !mScroller.isFinished(); + mIsBeingDragged = !mScroller.isFinished() || !mEdgeGlowBottom.isFinished() + || !mEdgeGlowTop.isFinished(); + // Catch the edge effect if it is active. + if (!mEdgeGlowTop.isFinished()) { + mEdgeGlowTop.onPullDistance(0f, ev.getX() / getWidth()); + } + if (!mEdgeGlowBottom.isFinished()) { + mEdgeGlowBottom.onPullDistance(0f, 1f - ev.getX() / getWidth()); + } if (mIsBeingDragged && mScrollStrictSpan == null) { mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll"); } @@ -732,7 +746,7 @@ public class ScrollView extends FrameLayout { if (getChildCount() == 0) { return false; } - if ((mIsBeingDragged = !mScroller.isFinished())) { + if (!mScroller.isFinished()) { final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); @@ -793,6 +807,21 @@ public class ScrollView extends FrameLayout { boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0); + final float displacement = ev.getX(activePointerIndex) / getWidth(); + if (canOverscroll) { + int consumed = 0; + if (deltaY < 0 && mEdgeGlowBottom.getDistance() != 0f) { + consumed = Math.round(getHeight() + * mEdgeGlowBottom.onPullDistance((float) deltaY / getHeight(), + 1 - displacement)); + } else if (deltaY > 0 && mEdgeGlowTop.getDistance() != 0f) { + consumed = Math.round(-getHeight() + * mEdgeGlowTop.onPullDistance((float) -deltaY / getHeight(), + displacement)); + } + deltaY -= consumed; + } + // Calling overScrollBy will call onOverScrolled, which // calls onScrollChanged if applicable. if (overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true) @@ -807,17 +836,17 @@ public class ScrollView extends FrameLayout { mLastMotionY -= mScrollOffset[1]; vtev.offsetLocation(0, mScrollOffset[1]); mNestedYOffset += mScrollOffset[1]; - } else if (canOverscroll) { + } else if (canOverscroll && deltaY != 0f) { final int pulledToY = oldY + deltaY; if (pulledToY < 0) { - mEdgeGlowTop.onPull((float) deltaY / getHeight(), - ev.getX(activePointerIndex) / getWidth()); + mEdgeGlowTop.onPullDistance((float) -deltaY / getHeight(), + displacement); if (!mEdgeGlowBottom.isFinished()) { mEdgeGlowBottom.onRelease(); } } else if (pulledToY > range) { - mEdgeGlowBottom.onPull((float) deltaY / getHeight(), - 1.f - ev.getX(activePointerIndex) / getWidth()); + mEdgeGlowBottom.onPullDistance((float) deltaY / getHeight(), + 1.f - displacement); if (!mEdgeGlowTop.isFinished()) { mEdgeGlowTop.onRelease(); } @@ -1745,9 +1774,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); + } } } } |
