Test: fling while overscrolled ScrollView/HorizontalScrollView
Bug: 186430321
ScrollView and HorizontalScrollView was not allowing a fling
effect while overscrolling. This adds tests to ensure that
ScrollView and HorizontalScrollView can fling
while overscrolling.
Test: new test
Test: manual ApiDemos
Change-Id: Idaf208460a12792ad97aec5a4a0e20fb696e09db
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
index 2b35073..8b7f6cf 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
@@ -17,6 +17,7 @@
package android.widget.cts;
import static android.widget.cts.util.StretchEdgeUtil.dragHoldAndRun;
+import static android.widget.cts.util.StretchEdgeUtil.fling;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -898,6 +899,37 @@
);
}
+ @Test
+ public void testFlingWhileStretchedLeft() throws Throwable {
+ // Make sure that the scroll view we care about is on screen and at the top:
+ showOnlyStretch();
+
+ ScrollViewTest.CaptureOnAbsorbEdgeEffect
+ edgeEffect = new ScrollViewTest.CaptureOnAbsorbEdgeEffect(mActivity);
+ mScrollViewStretch.mEdgeGlowLeft = edgeEffect;
+ fling(mActivityRule, mScrollViewStretch, 300, 0);
+ assertTrue("Expecting greater than 0, but was " + edgeEffect.onAbsorbVelocity,
+ edgeEffect.onAbsorbVelocity > 0);
+ }
+
+ @Test
+ public void testFlingWhileStretchedRight() throws Throwable {
+ // Make sure that the scroll view we care about is on screen and at the top:
+ showOnlyStretch();
+
+ mActivityRule.runOnUiThread(() -> {
+ // Scroll all the way to the bottom
+ mScrollViewStretch.scrollTo(210, 0);
+ });
+
+ ScrollViewTest.CaptureOnAbsorbEdgeEffect
+ edgeEffect = new ScrollViewTest.CaptureOnAbsorbEdgeEffect(mActivity);
+ mScrollViewStretch.mEdgeGlowRight = edgeEffect;
+ fling(mActivityRule, mScrollViewStretch, -300, 0);
+ assertTrue("Expecting greater than 0, but was " + edgeEffect.onAbsorbVelocity,
+ edgeEffect.onAbsorbVelocity > 0);
+ }
+
private void showOnlyStretch() throws Throwable {
mActivityRule.runOnUiThread(() -> {
mScrollViewCustom.setVisibility(View.GONE);
@@ -908,6 +940,8 @@
ArrayList exclusionRects = new ArrayList();
exclusionRects.add(exclusionRect);
mScrollViewStretch.setSystemGestureExclusionRects(exclusionRects);
+ mActivity.findViewById(R.id.wrapped_stretch)
+ .setSystemGestureExclusionRects(exclusionRects);
});
}
diff --git a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
index d94b491..9b29d13 100644
--- a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
@@ -17,6 +17,7 @@
package android.widget.cts;
import static android.widget.cts.util.StretchEdgeUtil.dragHoldAndRun;
+import static android.widget.cts.util.StretchEdgeUtil.fling;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -941,6 +942,33 @@
assertTrue(StretchEdgeUtil.dragUpTapAndHoldStretches(mActivityRule, mScrollViewStretch));
}
+ @Test
+ public void testFlingWhileStretchedTop() throws Throwable {
+ // Make sure that the scroll view we care about is on screen and at the top:
+ showOnlyStretch();
+
+ CaptureOnAbsorbEdgeEffect edgeEffect = new CaptureOnAbsorbEdgeEffect(mActivity);
+ mScrollViewStretch.mEdgeGlowTop = edgeEffect;
+ fling(mActivityRule, mScrollViewStretch, 0, 300);
+ assertTrue(edgeEffect.onAbsorbVelocity > 0);
+ }
+
+ @Test
+ public void testFlingWhileStretchedBottom() throws Throwable {
+ // Make sure that the scroll view we care about is on screen and at the top:
+ showOnlyStretch();
+
+ mActivityRule.runOnUiThread(() -> {
+ // Scroll all the way to the bottom
+ mScrollViewStretch.scrollTo(0, 210);
+ });
+
+ CaptureOnAbsorbEdgeEffect edgeEffect = new CaptureOnAbsorbEdgeEffect(mActivity);
+ mScrollViewStretch.mEdgeGlowBottom = edgeEffect;
+ fling(mActivityRule, mScrollViewStretch, 0, -300);
+ assertTrue(edgeEffect.onAbsorbVelocity > 0);
+ }
+
private void showOnlyStretch() throws Throwable {
mActivityRule.runOnUiThread(() -> {
mScrollViewCustom.setVisibility(View.GONE);
@@ -1090,4 +1118,18 @@
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
+
+ public static class CaptureOnAbsorbEdgeEffect extends EdgeEffect {
+ public int onAbsorbVelocity;
+
+ public CaptureOnAbsorbEdgeEffect(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onAbsorb(int velocity) {
+ onAbsorbVelocity = velocity;
+ super.onAbsorb(velocity);
+ }
+ }
}
diff --git a/tests/tests/widget/src/android/widget/cts/util/StretchEdgeUtil.kt b/tests/tests/widget/src/android/widget/cts/util/StretchEdgeUtil.kt
index ff744b0..7fa0682 100644
--- a/tests/tests/widget/src/android/widget/cts/util/StretchEdgeUtil.kt
+++ b/tests/tests/widget/src/android/widget/cts/util/StretchEdgeUtil.kt
@@ -84,7 +84,7 @@
* Drags an area of the screen and executes [onFinalMove] after sending the final drag
* motion and [onUp] after the drag up event has been sent.
*/
-public fun dragAndExecute(
+fun dragAndExecute(
activityRule: ActivityTestRule<*>,
screenX: Int,
screenY: Int,
@@ -118,6 +118,35 @@
}
/**
+ * Flings [view] from the center by ([deltaX], [deltaY]) pixels over 16 milliseconds.
+ */
+fun fling(
+ activityRule: ActivityTestRule<*>,
+ view: View,
+ deltaX: Int,
+ deltaY: Int
+) {
+ val locationOnScreen = IntArray(2)
+ activityRule.runOnUiThread {
+ view.getLocationOnScreen(locationOnScreen)
+ }
+
+ val screenX = locationOnScreen[0]
+ val screenY = locationOnScreen[1]
+ val instrumentation = InstrumentationRegistry.getInstrumentation()
+
+ CtsTouchUtils.emulateDragGesture(instrumentation, activityRule,
+ screenX + (view.width / 2),
+ screenY + (view.height / 2),
+ deltaX,
+ deltaY,
+ 16,
+ 4,
+ null
+ )
+}
+
+/**
* Drags inside [view] starting at coordinates ([viewX], [viewY]) relative to [view] and moving
* ([deltaX], [deltaY]) pixels before lifting. A Bitmap is captured after the final drag event,
* before the up event.