summaryrefslogtreecommitdiff
path: root/core/java/android/widget/ScrollView.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/widget/ScrollView.java')
-rw-r--r--core/java/android/widget/ScrollView.java57
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);
+ }
}
}
}