From 5ba19c973a92f55dc9685decf8aeb821f0cd064b Mon Sep 17 00:00:00 2001 From: Mark Renouf Date: Mon, 12 Apr 2021 17:09:21 -0400 Subject: [PATCH] Do not inset scrollBounds by padding unless clipToPadding==true The intent is to avoid attempting to capture areas of a scrollable view which will never display content. This is only the case when clipToPadding = true (which is the default). Bug: 185153400 Test: atest ScrollCaptureViewSupportTest Change-Id: I2d97ba480320c3e83c056c0f51d7b4ca51715bd6 --- .../view/ScrollCaptureViewHelper.java | 17 +++- .../view/ScrollCaptureViewSupportTest.java | 83 +++++++++++++++++++ 2 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 core/tests/coretests/src/com/android/internal/view/ScrollCaptureViewSupportTest.java diff --git a/core/java/com/android/internal/view/ScrollCaptureViewHelper.java b/core/java/com/android/internal/view/ScrollCaptureViewHelper.java index 9829d0b7ae8d6..356cd6b5c9fce 100644 --- a/core/java/com/android/internal/view/ScrollCaptureViewHelper.java +++ b/core/java/com/android/internal/view/ScrollCaptureViewHelper.java @@ -19,8 +19,14 @@ package com.android.internal.view; import android.annotation.NonNull; import android.graphics.Rect; import android.view.View; +import android.view.ViewGroup; -interface ScrollCaptureViewHelper { +/** + * Provides view-specific handling to ScrollCaptureViewSupport. + * + * @param the View subclass + */ +public interface ScrollCaptureViewHelper { int UP = -1; int DOWN = 1; @@ -73,9 +79,12 @@ interface ScrollCaptureViewHelper { * @param view the view being captured */ @NonNull default Rect onComputeScrollBounds(@NonNull V view) { - return new Rect(view.getPaddingLeft(), view.getPaddingTop(), - view.getWidth() - view.getPaddingRight(), - view.getHeight() - view.getPaddingBottom()); + Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight()); + if (view instanceof ViewGroup && ((ViewGroup) view).getClipToPadding()) { + bounds.inset(view.getPaddingLeft(), view.getPaddingTop(), + view.getPaddingRight(), view.getPaddingBottom()); + } + return bounds; } /** diff --git a/core/tests/coretests/src/com/android/internal/view/ScrollCaptureViewSupportTest.java b/core/tests/coretests/src/com/android/internal/view/ScrollCaptureViewSupportTest.java new file mode 100644 index 0000000000000..cb72b2d0f0122 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/view/ScrollCaptureViewSupportTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.view; + +import static org.junit.Assert.assertEquals; + +import android.content.Context; +import android.graphics.Rect; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.Test; + +public class ScrollCaptureViewSupportTest { + + ScrollCaptureViewHelper mViewHelper = new ScrollCaptureViewHelper() { + @Override + public void onPrepareForStart(@NonNull View view, @NonNull Rect scrollBounds) { + } + + @NonNull + @Override + public ScrollResult onScrollRequested(@NonNull View view, @NonNull Rect scrollBounds, + @NonNull Rect requestRect) { + return new ScrollResult(); + } + + @Override + public void onPrepareForEnd(@NonNull View view) { + } + }; + + + /** + * Test scroll bounds are computed correctly. onComputeScrollBounds is currently a + * default interface method of ScrollCaptureViewHelper. + */ + @Test + public void testComputeScrollBounds() { + Context context = InstrumentationRegistry.getInstrumentation().getContext(); + + ViewGroup target = new ViewGroup(context) { + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + // n/a + } + }; + + target.setPadding(25, 50, 25, 50); + target.setLeftTopRightBottom(0, 0, 200, 200); + + + // clipToPadding == false: No effect + target.setClipToPadding(false); + Rect scrollBounds = mViewHelper.onComputeScrollBounds(target); + assertEquals("Computed scroll bounds are incorrect with clipToPadding=false", + new Rect(0, 0, 200, 200), scrollBounds); + + // clipToPadding == true: Inset by padding + target.setClipToPadding(true); + scrollBounds = mViewHelper.onComputeScrollBounds(target); + assertEquals("Computed scroll bounds are incorrect with clipToPadding=true", + new Rect(25, 50, 175, 150), scrollBounds); + } + +}