diff options
9 files changed, 478 insertions, 0 deletions
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 1d6778b8a4a9..55b2251ac196 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -1498,6 +1498,11 @@ public class HorizontalScrollView extends FrameLayout { * @return The unconsumed delta after the EdgeEffects have had an opportunity to consume. */ private int consumeFlingInStretch(int unconsumed) { + int scrollX = getScrollX(); + if (scrollX < 0 || scrollX > getScrollRange()) { + // We've overscrolled, so don't stretch + return unconsumed; + } if (unconsumed > 0 && mEdgeGlowLeft != null && mEdgeGlowLeft.getDistance() != 0f) { int size = getWidth(); float deltaDistance = -unconsumed * FLING_DESTRETCH_FACTOR / size; diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index eeb6b43a89f2..d330ebf73323 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -1566,6 +1566,11 @@ public class ScrollView extends FrameLayout { * @return The unconsumed delta after the EdgeEffects have had an opportunity to consume. */ private int consumeFlingInStretch(int unconsumed) { + int scrollY = getScrollY(); + if (scrollY < 0 || scrollY > getScrollRange()) { + // We've overscrolled, so don't stretch + return unconsumed; + } if (unconsumed > 0 && mEdgeGlowTop != null && mEdgeGlowTop.getDistance() != 0f) { int size = getHeight(); float deltaDistance = -unconsumed * FLING_DESTRETCH_FACTOR / size; diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 129de649a4b5..31755efb88ed 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -231,6 +231,28 @@ </intent-filter> </activity> + <activity android:name="android.widget.HorizontalScrollViewActivity" + android:label="HorizontalScrollViewActivity" + android:screenOrientation="portrait" + android:exported="true" + android:theme="@android:style/Theme.Material.Light"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" /> + </intent-filter> + </activity> + + <activity android:name="android.widget.ScrollViewActivity" + android:label="ScrollViewActivity" + android:screenOrientation="portrait" + android:exported="true" + android:theme="@android:style/Theme.Material.Light"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" /> + </intent-filter> + </activity> + <activity android:name="android.widget.DatePickerActivity" android:label="DatePickerActivity" android:screenOrientation="portrait" diff --git a/core/tests/coretests/res/layout/activity_horizontal_scroll_view.xml b/core/tests/coretests/res/layout/activity_horizontal_scroll_view.xml new file mode 100644 index 000000000000..866e1a95c3f5 --- /dev/null +++ b/core/tests/coretests/res/layout/activity_horizontal_scroll_view.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2015 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 + --> + +<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/horizontal_scroll_view"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <View + android:background="#F00" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#880" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#0F0" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#088" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#00F" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#808" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#F00" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#880" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#0F0" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#088" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#00F" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#808" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#F00" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#880" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#0F0" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#088" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#00F" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#808" + android:layout_width="100dp" + android:layout_height="100dp" /> + + </LinearLayout> +</HorizontalScrollView> diff --git a/core/tests/coretests/res/layout/activity_scroll_view.xml b/core/tests/coretests/res/layout/activity_scroll_view.xml new file mode 100644 index 000000000000..61fabf8ee437 --- /dev/null +++ b/core/tests/coretests/res/layout/activity_scroll_view.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2015 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 + --> + +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/scroll_view"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <View + android:background="#F00" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#880" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#0F0" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#088" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#00F" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#808" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#F00" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#880" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#0F0" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#088" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#00F" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#808" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#F00" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#880" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#0F0" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#088" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#00F" + android:layout_width="100dp" + android:layout_height="100dp" /> + + <View + android:background="#808" + android:layout_width="100dp" + android:layout_height="100dp" /> + + </LinearLayout> +</ScrollView> diff --git a/core/tests/coretests/src/android/widget/HorizontalScrollViewActivity.java b/core/tests/coretests/src/android/widget/HorizontalScrollViewActivity.java new file mode 100644 index 000000000000..21013545008c --- /dev/null +++ b/core/tests/coretests/src/android/widget/HorizontalScrollViewActivity.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 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 android.widget; + +import android.app.Activity; +import android.os.Bundle; + +import com.android.frameworks.coretests.R; + +/** + * An activity for testing the TextView widget. + */ +public class HorizontalScrollViewActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_horizontal_scroll_view); + } +} diff --git a/core/tests/coretests/src/android/widget/HorizontalScrollViewFunctionalTest.java b/core/tests/coretests/src/android/widget/HorizontalScrollViewFunctionalTest.java new file mode 100644 index 000000000000..86f26e59e370 --- /dev/null +++ b/core/tests/coretests/src/android/widget/HorizontalScrollViewFunctionalTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 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 android.widget; + +import static org.junit.Assert.assertEquals; + +import android.platform.test.annotations.Presubmit; +import android.util.PollingCheck; + +import androidx.test.filters.MediumTest; +import androidx.test.rule.ActivityTestRule; +import androidx.test.runner.AndroidJUnit4; + +import com.android.frameworks.coretests.R; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@MediumTest +@Presubmit +public class HorizontalScrollViewFunctionalTest { + private HorizontalScrollViewActivity mActivity; + private HorizontalScrollView mHorizontalScrollView; + @Rule + public ActivityTestRule<HorizontalScrollViewActivity> mActivityRule = new ActivityTestRule<>( + HorizontalScrollViewActivity.class); + + @Before + public void setUp() throws Exception { + mActivity = mActivityRule.getActivity(); + mHorizontalScrollView = mActivity.findViewById(R.id.horizontal_scroll_view); + } + + @Test + public void testScrollAfterFlingTop() { + mHorizontalScrollView.scrollTo(100, 0); + mHorizontalScrollView.fling(-10000); + PollingCheck.waitFor(() -> mHorizontalScrollView.mEdgeGlowLeft.getDistance() > 0); + PollingCheck.waitFor(() -> mHorizontalScrollView.mEdgeGlowLeft.getDistance() == 0f); + assertEquals(0, mHorizontalScrollView.getScrollX()); + } + + @Test + public void testScrollAfterFlingBottom() { + int childWidth = mHorizontalScrollView.getChildAt(0).getWidth(); + int maxScroll = childWidth - mHorizontalScrollView.getWidth(); + mHorizontalScrollView.scrollTo(maxScroll - 100, 0); + mHorizontalScrollView.fling(10000); + PollingCheck.waitFor(() -> mHorizontalScrollView.mEdgeGlowRight.getDistance() > 0); + PollingCheck.waitFor(() -> mHorizontalScrollView.mEdgeGlowRight.getDistance() == 0f); + assertEquals(maxScroll, mHorizontalScrollView.getScrollX()); + } +} + diff --git a/core/tests/coretests/src/android/widget/ScrollViewActivity.java b/core/tests/coretests/src/android/widget/ScrollViewActivity.java new file mode 100644 index 000000000000..899d63163aa4 --- /dev/null +++ b/core/tests/coretests/src/android/widget/ScrollViewActivity.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 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 android.widget; + +import android.app.Activity; +import android.os.Bundle; + +import com.android.frameworks.coretests.R; + +/** + * An activity for testing the TextView widget. + */ +public class ScrollViewActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_scroll_view); + } +} diff --git a/core/tests/coretests/src/android/widget/ScrollViewFunctionalTest.java b/core/tests/coretests/src/android/widget/ScrollViewFunctionalTest.java new file mode 100644 index 000000000000..a49bb6af13d2 --- /dev/null +++ b/core/tests/coretests/src/android/widget/ScrollViewFunctionalTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 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 android.widget; + +import static org.junit.Assert.assertEquals; + +import android.platform.test.annotations.Presubmit; +import android.util.PollingCheck; + +import androidx.test.filters.MediumTest; +import androidx.test.rule.ActivityTestRule; +import androidx.test.runner.AndroidJUnit4; + +import com.android.frameworks.coretests.R; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@MediumTest +@Presubmit +public class ScrollViewFunctionalTest { + private ScrollViewActivity mActivity; + private ScrollView mScrollView; + @Rule + public ActivityTestRule<ScrollViewActivity> mActivityRule = new ActivityTestRule<>( + ScrollViewActivity.class); + + @Before + public void setUp() throws Exception { + mActivity = mActivityRule.getActivity(); + mScrollView = mActivity.findViewById(R.id.scroll_view); + } + + @Test + public void testScrollAfterFlingTop() { + mScrollView.scrollTo(0, 100); + mScrollView.fling(-10000); + PollingCheck.waitFor(() -> mScrollView.mEdgeGlowTop.getDistance() > 0); + PollingCheck.waitFor(() -> mScrollView.mEdgeGlowTop.getDistance() == 0f); + assertEquals(0, mScrollView.getScrollY()); + } + + @Test + public void testScrollAfterFlingBottom() { + int childHeight = mScrollView.getChildAt(0).getHeight(); + int maxScroll = childHeight - mScrollView.getHeight(); + mScrollView.scrollTo(0, maxScroll - 100); + mScrollView.fling(10000); + PollingCheck.waitFor(() -> mScrollView.mEdgeGlowBottom.getDistance() > 0); + PollingCheck.waitFor(() -> mScrollView.mEdgeGlowBottom.getDistance() == 0f); + assertEquals(maxScroll, mScrollView.getScrollY()); + } +} + |