summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/ViewGroup.java21
-rw-r--r--core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java83
3 files changed, 91 insertions, 15 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 03c40cb03d6f..bed5eea2d199 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1494,7 +1494,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public static final int SCROLL_CAPTURE_HINT_AUTO = 0;
/**
- * Explicitly exclcude this view as a potential scroll capture target. The system will not
+ * Explicitly exclude this view as a potential scroll capture target. The system will not
* consider it. Mutually exclusive with {@link #SCROLL_CAPTURE_HINT_INCLUDE}, which this flag
* takes precedence over.
*
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 04e2cdee56a0..a02281be1228 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -7490,12 +7490,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
@NonNull Rect localVisibleRect, @NonNull Point windowOffset,
@NonNull Consumer<ScrollCaptureTarget> targets) {
- // copy local visible rect for modification and dispatch
- final Rect rect = getTempRect();
- rect.set(localVisibleRect);
-
- if (getClipToPadding()) {
- rect.inset(mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom);
+ if (getClipToPadding() && !localVisibleRect.intersect(mPaddingLeft, mPaddingTop,
+ (mRight - mLeft) - mPaddingRight, (mBottom - mTop) - mPaddingBottom)) {
+ return;
}
// Dispatch to self first.
@@ -7506,6 +7503,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return;
}
+ final Rect tmpRect = getTempRect();
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -7518,8 +7516,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// If the resulting rectangle is not empty, the request is forwarded to the child.
// copy local visible rect for modification and dispatch
- final Rect childVisibleRect = getTempRect();
- childVisibleRect.set(localVisibleRect);
+ tmpRect.set(localVisibleRect);
// transform to child coords
final Point childWindowOffset = getTempPoint();
@@ -7528,20 +7525,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final int dx = child.mLeft - mScrollX;
final int dy = child.mTop - mScrollY;
- childVisibleRect.offset(-dx, -dy);
+ tmpRect.offset(-dx, -dy);
childWindowOffset.offset(dx, dy);
boolean rectIsVisible = true;
// Clip to child bounds
if (getClipChildren()) {
- rectIsVisible = childVisibleRect.intersect(0, 0, child.getWidth(),
- child.getHeight());
+ rectIsVisible = tmpRect.intersect(0, 0, child.getWidth(), child.getHeight());
}
- // Clip to child padding.
if (rectIsVisible) {
- child.dispatchScrollCaptureSearch(childVisibleRect, childWindowOffset, targets);
+ child.dispatchScrollCaptureSearch(tmpRect, childWindowOffset, targets);
}
}
}
diff --git a/core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java b/core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java
index 695eb0ced756..25608c328f95 100644
--- a/core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java
+++ b/core/tests/coretests/src/android/view/ViewGroupScrollCaptureTest.java
@@ -33,7 +33,6 @@ import android.os.CancellationSignal;
import android.platform.test.annotations.Presubmit;
import androidx.annotation.NonNull;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
@@ -355,6 +354,54 @@ public class ViewGroupScrollCaptureTest {
target.getContainingView().getScrollCaptureHint());
}
+ /**
+ * Tests the effect of padding on scroll capture search dispatch.
+ * <p>
+ * Verifies computation of child visible bounds with padding.
+ */
+ @MediumTest
+ @Test
+ public void testOnScrollCaptureSearch_withPadding() {
+ final Context context = getInstrumentation().getContext();
+
+ Rect windowBounds = new Rect(0, 0, 200, 200);
+ Point windowOffset = new Point(0, 0);
+
+ final MockViewGroup parent = new MockViewGroup(context, 0, 0, 200, 200);
+ parent.setPadding(25, 50, 25, 50);
+ parent.setClipToPadding(true); // (default)
+
+ final MockView view1 = new MockView(context, 0, -100, 200, 100);
+ parent.addView(view1);
+
+ final MockView view2 = new MockView(context, 0, 0, 200, 200);
+ parent.addView(view2);
+
+ final MockViewGroup view3 = new MockViewGroup(context, 0, 100, 200, 300);
+ parent.addView(view3);
+ view3.setPadding(25, 25, 25, 25);
+ view3.setClipToPadding(true);
+
+ // Where targets are added
+ final ScrollCaptureSearchResults results = new ScrollCaptureSearchResults(DIRECT_EXECUTOR);
+
+ // Dispatch to the ViewGroup
+ parent.dispatchScrollCaptureSearch(windowBounds, windowOffset, results::addTarget);
+
+ // Verify padding (with clipToPadding) is subtracted from visibleBounds
+ parent.assertOnScrollCaptureSearchLastArgs(new Rect(25, 50, 175, 150), new Point(0, 0));
+
+ view1.assertOnScrollCaptureSearchLastArgs(
+ new Rect(25, 150, 175, 200), new Point(0, -100));
+
+ view2.assertOnScrollCaptureSearchLastArgs(
+ new Rect(25, 50, 175, 150), new Point(0, 0));
+
+ // Account for padding on view3 as well (top == 25px)
+ view3.assertOnScrollCaptureSearchLastArgs(
+ new Rect(25, 25, 175, 50), new Point(0, 100));
+ }
+
public static final class MockView extends View {
private ScrollCaptureCallback mInternalCallback;
@@ -362,6 +409,8 @@ public class ViewGroupScrollCaptureTest {
private Rect mDispatchScrollCaptureSearchLastLocalVisibleRect;
private Point mDispatchScrollCaptureSearchLastWindowOffset;
private int mCreateScrollCaptureCallbackInternalCount;
+ private Rect mOnScrollCaptureSearchLastLocalVisibleRect;
+ private Point mOnScrollCaptureSearchLastWindowOffset;
MockView(Context context) {
this(context, /* left */ 0, /* top */0, /* right */ 0, /* bottom */0);
@@ -407,6 +456,21 @@ public class ViewGroupScrollCaptureTest {
}
@Override
+ public void onScrollCaptureSearch(Rect localVisibleRect, Point windowOffset,
+ Consumer<ScrollCaptureTarget> targets) {
+ super.onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
+ mOnScrollCaptureSearchLastLocalVisibleRect = new Rect(localVisibleRect);
+ mOnScrollCaptureSearchLastWindowOffset = new Point(windowOffset);
+ }
+
+ void assertOnScrollCaptureSearchLastArgs(Rect localVisibleRect, Point windowOffset) {
+ assertEquals("arg localVisibleRect was incorrect.",
+ localVisibleRect, mOnScrollCaptureSearchLastLocalVisibleRect);
+ assertEquals("arg windowOffset was incorrect.",
+ windowOffset, mOnScrollCaptureSearchLastWindowOffset);
+ }
+
+ @Override
public void dispatchScrollCaptureSearch(Rect localVisibleRect, Point windowOffset,
Consumer<ScrollCaptureTarget> results) {
mDispatchScrollCaptureSearchNumCalls++;
@@ -449,6 +513,8 @@ public class ViewGroupScrollCaptureTest {
public static final class MockViewGroup extends ViewGroup {
private ScrollCaptureCallback mInternalCallback;
+ private Rect mOnScrollCaptureSearchLastLocalVisibleRect;
+ private Point mOnScrollCaptureSearchLastWindowOffset;
MockViewGroup(Context context) {
this(context, /* left */ 0, /* top */0, /* right */ 0, /* bottom */0);
@@ -477,6 +543,21 @@ public class ViewGroupScrollCaptureTest {
}
@Override
+ public void onScrollCaptureSearch(Rect localVisibleRect, Point windowOffset,
+ Consumer<ScrollCaptureTarget> targets) {
+ super.onScrollCaptureSearch(localVisibleRect, windowOffset, targets);
+ mOnScrollCaptureSearchLastLocalVisibleRect = new Rect(localVisibleRect);
+ mOnScrollCaptureSearchLastWindowOffset = new Point(windowOffset);
+ }
+
+ void assertOnScrollCaptureSearchLastArgs(Rect localVisibleRect, Point windowOffset) {
+ assertEquals("arg localVisibleRect was incorrect.",
+ localVisibleRect, mOnScrollCaptureSearchLastLocalVisibleRect);
+ assertEquals("arg windowOffset was incorrect.",
+ windowOffset, mOnScrollCaptureSearchLastWindowOffset);
+ }
+
+ @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// We don't layout this view.
}