From 33e79a15da6ccce4565c210009be1c56f9f4af18 Mon Sep 17 00:00:00 2001 From: George Mount Date: Thu, 16 Dec 2021 15:31:59 -0800 Subject: [PATCH] Allow watch rotary to trigger stretch on scrolling containers. Bug: 204794759 Rotary scrolling should trigger the stretch edge effect. Mouse scrolling should NOT trigger the stretch edge effect. This adds support for rotary scrolling while keeping mouse scrolling from triggering the edge effect. Test: new CTS tests. manual testing on emulator Change-Id: Ibad25bcbc0740f2af2042baf67f7606f15b8c57e --- core/java/android/widget/AbsListView.java | 27 +++++++++++++++++++ .../android/widget/HorizontalScrollView.java | 24 +++++++++++++++++ core/java/android/widget/ScrollView.java | 23 ++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 1d8e9a36fb3f1..588ff52d23e63 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -4363,8 +4363,35 @@ public abstract class AbsListView extends AdapterView implements Te final int delta = Math.round(axisValue * mVerticalScrollFactor); if (delta != 0) { + // If we're moving down, we want the top item. If we're moving up, bottom item. + final int motionIndex = delta > 0 ? 0 : getChildCount() - 1; + + int motionViewPrevTop = 0; + View motionView = this.getChildAt(motionIndex); + if (motionView != null) { + motionViewPrevTop = motionView.getTop(); + } + + final int overscrollMode = getOverScrollMode(); + if (!trackMotionScroll(delta, delta)) { return true; + } else if (!event.isFromSource(InputDevice.SOURCE_MOUSE) && motionView != null + && (overscrollMode == OVER_SCROLL_ALWAYS + || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS + && !contentFits()))) { + int motionViewRealTop = motionView.getTop(); + float overscroll = (delta - (motionViewRealTop - motionViewPrevTop)) + / ((float) getHeight()); + if (delta > 0) { + mEdgeGlowTop.onPullDistance(overscroll, 0.5f); + mEdgeGlowTop.onRelease(); + } else { + mEdgeGlowBottom.onPullDistance(-overscroll, 0.5f); + mEdgeGlowBottom.onRelease(); + } + invalidate(); + return true; } } break; diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 018cba7f95e5c..2dbfd7e5b2e26 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -872,15 +872,39 @@ public class HorizontalScrollView extends FrameLayout { final int range = getScrollRange(); int oldScrollX = mScrollX; int newScrollX = oldScrollX + delta; + + final int overscrollMode = getOverScrollMode(); + boolean canOverscroll = !event.isFromSource(InputDevice.SOURCE_MOUSE) + && (overscrollMode == OVER_SCROLL_ALWAYS + || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0)); + boolean absorbed = false; + if (newScrollX < 0) { + if (canOverscroll) { + mEdgeGlowLeft.onPullDistance(-(float) newScrollX / getWidth(), + 0.5f); + mEdgeGlowLeft.onRelease(); + invalidate(); + absorbed = true; + } newScrollX = 0; } else if (newScrollX > range) { + if (canOverscroll) { + mEdgeGlowRight.onPullDistance( + (float) (newScrollX - range) / getWidth(), 0.5f); + mEdgeGlowRight.onRelease(); + invalidate(); + absorbed = true; + } newScrollX = range; } if (newScrollX != oldScrollX) { super.scrollTo(newScrollX, mScrollY); return true; } + if (absorbed) { + return true; + } } } } diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 15cd17b20f4f0..2acd50c9e169b 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -939,15 +939,38 @@ public class ScrollView extends FrameLayout { final int range = getScrollRange(); int oldScrollY = mScrollY; int newScrollY = oldScrollY - delta; + + final int overscrollMode = getOverScrollMode(); + boolean canOverscroll = !event.isFromSource(InputDevice.SOURCE_MOUSE) + && (overscrollMode == OVER_SCROLL_ALWAYS + || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0)); + boolean absorbed = false; + if (newScrollY < 0) { + if (canOverscroll) { + mEdgeGlowTop.onPullDistance(-(float) newScrollY / getHeight(), 0.5f); + mEdgeGlowTop.onRelease(); + invalidate(); + absorbed = true; + } newScrollY = 0; } else if (newScrollY > range) { + if (canOverscroll) { + mEdgeGlowBottom.onPullDistance( + (float) (newScrollY - range) / getHeight(), 0.5f); + mEdgeGlowBottom.onRelease(); + invalidate(); + absorbed = true; + } newScrollY = range; } if (newScrollY != oldScrollY) { super.scrollTo(mScrollX, newScrollY); return true; } + if (absorbed) { + return true; + } } break; }