1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.widget.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertSame; 22 import static org.junit.Assert.assertTrue; 23 import static org.junit.Assert.fail; 24 import static org.mockito.Matchers.eq; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.verify; 27 28 import android.app.Activity; 29 import android.app.Instrumentation; 30 import android.content.Context; 31 import android.graphics.Rect; 32 import android.support.test.InstrumentationRegistry; 33 import android.support.test.annotation.UiThreadTest; 34 import android.support.test.filters.MediumTest; 35 import android.support.test.rule.ActivityTestRule; 36 import android.support.test.runner.AndroidJUnit4; 37 import android.util.AttributeSet; 38 import android.util.Xml; 39 import android.view.View; 40 import android.view.View.MeasureSpec; 41 import android.view.ViewGroup; 42 import android.widget.FrameLayout; 43 import android.widget.HorizontalScrollView; 44 import android.widget.TextView; 45 46 import com.android.compatibility.common.util.PollingCheck; 47 import com.android.compatibility.common.util.WidgetTestUtils; 48 49 import org.junit.Before; 50 import org.junit.Rule; 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 import org.xmlpull.v1.XmlPullParser; 54 55 /** 56 * Test {@link HorizontalScrollView}. 57 */ 58 @MediumTest 59 @RunWith(AndroidJUnit4.class) 60 public class HorizontalScrollViewTest { 61 private static final int ITEM_WIDTH = 250; 62 private static final int ITEM_HEIGHT = 100; 63 private static final int ITEM_COUNT = 15; 64 private static final int PAGE_WIDTH = 100; 65 private static final int PAGE_HEIGHT = 100; 66 private static final int SCROLL_RIGHT = ITEM_WIDTH * ITEM_COUNT - PAGE_WIDTH; 67 68 private Instrumentation mInstrumentation; 69 private Activity mActivity; 70 private HorizontalScrollView mScrollViewRegular; 71 private HorizontalScrollView mScrollViewCustom; 72 private MyHorizontalScrollView mScrollViewCustomEmpty; 73 74 @Rule 75 public ActivityTestRule<HorizontalScrollViewCtsActivity> mActivityRule = 76 new ActivityTestRule<>(HorizontalScrollViewCtsActivity.class); 77 78 @Before 79 public void setup() { 80 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 81 mActivity = mActivityRule.getActivity(); 82 mScrollViewRegular = (HorizontalScrollView) mActivity.findViewById( 83 R.id.horizontal_scroll_view_regular); 84 mScrollViewCustom = (MyHorizontalScrollView) mActivity.findViewById( 85 R.id.horizontal_scroll_view_custom); 86 mScrollViewCustomEmpty = (MyHorizontalScrollView) mActivity.findViewById( 87 R.id.horizontal_scroll_view_custom_empty); 88 } 89 90 @Test 91 public void testConstructor() { 92 XmlPullParser parser = mActivity.getResources().getLayout(R.layout.horizontal_scrollview); 93 AttributeSet attrs = Xml.asAttributeSet(parser); 94 new HorizontalScrollView(mActivity); 95 96 new HorizontalScrollView(mActivity, attrs); 97 98 new HorizontalScrollView(mActivity, attrs, 0); 99 } 100 101 @UiThreadTest 102 @Test 103 public void testGetMaxScrollAmount() { 104 mScrollViewRegular.layout(0, 0, 100, 200); 105 assertEquals((100 - 0) / 2, mScrollViewRegular.getMaxScrollAmount()); 106 107 mScrollViewRegular.layout(0, 0, 150, 100); 108 assertEquals((150 - 0) / 2, mScrollViewRegular.getMaxScrollAmount()); 109 } 110 111 @UiThreadTest 112 @Test 113 public void testAddView() { 114 TextView child0 = new TextView(mActivity); 115 mScrollViewRegular.addView(child0); 116 assertSame(child0, mScrollViewRegular.getChildAt(0)); 117 118 assertEquals(1, mScrollViewRegular.getChildCount()); 119 TextView child1 = new TextView(mActivity); 120 try { 121 mScrollViewRegular.addView(child1); 122 fail("did not throw IllegalStateException when add more than one child"); 123 } catch (IllegalStateException e) { 124 // expected 125 } 126 assertEquals(1, mScrollViewRegular.getChildCount()); 127 } 128 129 @UiThreadTest 130 @Test 131 public void testAddViewWithIndex() { 132 TextView child0 = new TextView(mActivity); 133 mScrollViewRegular.addView(child0, 0); 134 assertSame(child0, mScrollViewRegular.getChildAt(0)); 135 136 assertEquals(1, mScrollViewRegular.getChildCount()); 137 TextView child1 = new TextView(mActivity); 138 try { 139 mScrollViewRegular.addView(child1, 1); 140 fail("did not throw IllegalStateException when add more than one child"); 141 } catch (IllegalStateException e) { 142 // expected 143 } 144 assertEquals(1, mScrollViewRegular.getChildCount()); 145 146 mScrollViewRegular.removeAllViews(); 147 148 mScrollViewRegular.addView(child0, -1); 149 assertSame(child0, mScrollViewRegular.getChildAt(0)); 150 151 assertEquals(1, mScrollViewRegular.getChildCount()); 152 child1 = new TextView(mActivity); 153 try { 154 mScrollViewRegular.addView(child1, -1); 155 fail("did not throw IllegalStateException when add more than one child"); 156 } catch (IllegalStateException e) { 157 // expected 158 } 159 assertEquals(1, mScrollViewRegular.getChildCount()); 160 161 mScrollViewRegular.removeAllViews(); 162 163 try { 164 mScrollViewRegular.addView(child0, 1); 165 fail("did not throw IndexOutOfBoundsException when index is larger than 0"); 166 } catch (IndexOutOfBoundsException e) { 167 // expected 168 } 169 } 170 171 @UiThreadTest 172 @Test 173 public void testAddViewWithLayoutParams() { 174 TextView child0 = new TextView(mActivity); 175 mScrollViewRegular.addView(child0, new ViewGroup.LayoutParams(200, 100)); 176 assertSame(child0, mScrollViewRegular.getChildAt(0)); 177 assertEquals(200, child0.getLayoutParams().width); 178 assertEquals(100, child0.getLayoutParams().height); 179 180 assertEquals(1, mScrollViewRegular.getChildCount()); 181 TextView child1 = new TextView(mActivity); 182 try { 183 mScrollViewRegular.addView(child1, new ViewGroup.LayoutParams(200, 100)); 184 fail("did not throw IllegalStateException when add more than one child"); 185 } catch (IllegalStateException e) { 186 // expected 187 } 188 assertEquals(1, mScrollViewRegular.getChildCount()); 189 190 mScrollViewRegular.removeAllViews(); 191 child0 = new TextView(mActivity); 192 193 try { 194 mScrollViewRegular.addView(child0, null); 195 fail("did not throw NullPointerException when LayoutParams is null."); 196 } catch (NullPointerException e) { 197 // expected 198 } 199 } 200 201 @UiThreadTest 202 @Test 203 public void testAddViewWithIndexAndLayoutParams() { 204 TextView child0 = new TextView(mActivity); 205 mScrollViewRegular.addView(child0, 0, new ViewGroup.LayoutParams(200, 100)); 206 assertSame(child0, mScrollViewRegular.getChildAt(0)); 207 assertEquals(200, child0.getLayoutParams().width); 208 assertEquals(100, child0.getLayoutParams().height); 209 210 assertEquals(1, mScrollViewRegular.getChildCount()); 211 TextView child1 = new TextView(mActivity); 212 try { 213 mScrollViewRegular.addView(child1, 0, new ViewGroup.LayoutParams(200, 100)); 214 fail("did not throw IllegalStateException when add more than one child"); 215 } catch (IllegalStateException e) { 216 // expected 217 } 218 assertEquals(1, mScrollViewRegular.getChildCount()); 219 220 mScrollViewRegular.removeAllViews(); 221 222 child0 = new TextView(mActivity); 223 try { 224 mScrollViewRegular.addView(child0, null); 225 fail("did not throw NullPointerException when LayoutParams is null."); 226 } catch (NullPointerException e) { 227 // expected 228 } 229 230 mScrollViewRegular.removeAllViews(); 231 232 mScrollViewRegular.addView(child0, -1, new ViewGroup.LayoutParams(300, 150)); 233 assertSame(child0, mScrollViewRegular.getChildAt(0)); 234 assertEquals(300, child0.getLayoutParams().width); 235 assertEquals(150, child0.getLayoutParams().height); 236 237 assertEquals(1, mScrollViewRegular.getChildCount()); 238 child1 = new TextView(mActivity); 239 try { 240 mScrollViewRegular.addView(child1, -1, new ViewGroup.LayoutParams(200, 100)); 241 fail("did not throw IllegalStateException when add more than one child"); 242 } catch (IllegalStateException e) { 243 // expected 244 } 245 assertEquals(1, mScrollViewRegular.getChildCount()); 246 247 mScrollViewRegular.removeAllViews(); 248 249 try { 250 mScrollViewRegular.addView(child0, 1, new ViewGroup.LayoutParams(200, 100)); 251 fail("did not throw IndexOutOfBoundsException when index is larger than 0"); 252 } catch (IndexOutOfBoundsException e) { 253 // expected 254 } 255 } 256 257 @UiThreadTest 258 @Test 259 public void testAccessFillViewport() { 260 assertFalse(mScrollViewRegular.isFillViewport()); 261 mScrollViewRegular.layout(0, 0, 100, 100); 262 assertFalse(mScrollViewRegular.isLayoutRequested()); 263 264 mScrollViewRegular.setFillViewport(false); 265 assertFalse(mScrollViewRegular.isFillViewport()); 266 assertFalse(mScrollViewRegular.isLayoutRequested()); 267 268 mScrollViewRegular.setFillViewport(true); 269 assertTrue(mScrollViewRegular.isFillViewport()); 270 assertTrue(mScrollViewRegular.isLayoutRequested()); 271 272 mScrollViewRegular.layout(0, 0, 100, 100); 273 assertFalse(mScrollViewCustom.isLayoutRequested()); 274 275 mScrollViewRegular.setFillViewport(false); 276 assertFalse(mScrollViewRegular.isFillViewport()); 277 assertTrue(mScrollViewRegular.isLayoutRequested()); 278 } 279 280 @Test 281 public void testAccessSmoothScrollingEnabled() throws Throwable { 282 assertTrue(mScrollViewCustom.isSmoothScrollingEnabled()); 283 284 // scroll immediately 285 mScrollViewCustom.setSmoothScrollingEnabled(false); 286 assertFalse(mScrollViewCustom.isSmoothScrollingEnabled()); 287 288 mActivityRule.runOnUiThread(() -> mScrollViewCustom.fullScroll(View.FOCUS_RIGHT)); 289 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 290 291 mActivityRule.runOnUiThread(() -> mScrollViewCustom.fullScroll(View.FOCUS_LEFT)); 292 assertEquals(0, mScrollViewCustom.getScrollX()); 293 294 // smooth scroll 295 mScrollViewCustom.setSmoothScrollingEnabled(true); 296 assertTrue(mScrollViewCustom.isSmoothScrollingEnabled()); 297 298 mActivityRule.runOnUiThread(() -> mScrollViewCustom.fullScroll(View.FOCUS_RIGHT)); 299 pollingCheckSmoothScrolling(0, SCROLL_RIGHT, 0, 0); 300 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 301 302 mActivityRule.runOnUiThread(() -> mScrollViewCustom.fullScroll(View.FOCUS_LEFT)); 303 pollingCheckSmoothScrolling(SCROLL_RIGHT, 0, 0, 0); 304 assertEquals(0, mScrollViewCustom.getScrollX()); 305 } 306 307 @UiThreadTest 308 @Test 309 public void testMeasureChild() { 310 MyView child = new MyView(mActivity); 311 child.setBackgroundDrawable(null); 312 child.setPadding(0, 0, 0, 0); 313 child.setMinimumWidth(30); 314 child.setLayoutParams(new ViewGroup.LayoutParams(100, 100)); 315 child.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 316 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY)); 317 318 assertEquals(100, child.getMeasuredHeight()); 319 assertEquals(100, child.getMeasuredWidth()); 320 321 ((MyHorizontalScrollView) mScrollViewCustom).measureChild( 322 child, MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 323 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY)); 324 325 assertEquals(100, child.getMeasuredHeight()); 326 assertEquals(30, child.getMeasuredWidth()); 327 } 328 329 @UiThreadTest 330 @Test 331 public void testMeasureChildWithMargins() { 332 MyView child = new MyView(mActivity); 333 child.setBackgroundDrawable(null); 334 child.setPadding(0, 0, 0, 0); 335 child.setMinimumWidth(30); 336 child.setLayoutParams(new ViewGroup.MarginLayoutParams(100, 100)); 337 child.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 338 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY)); 339 340 assertEquals(100, child.getMeasuredHeight()); 341 assertEquals(100, child.getMeasuredWidth()); 342 343 ((MyHorizontalScrollView) mScrollViewCustom).measureChildWithMargins(child, 344 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 5, 345 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 5); 346 347 assertEquals(100, child.getMeasuredHeight()); 348 assertEquals(30, child.getMeasuredWidth()); 349 } 350 351 @UiThreadTest 352 @Test 353 public void testMeasureSpecs() { 354 MyView child = spy(new MyView(mActivity)); 355 mScrollViewCustomEmpty.addView(child); 356 357 mScrollViewCustomEmpty.measureChild(child, 358 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 359 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY)); 360 verify(child).onMeasure( 361 eq(MeasureSpec.makeMeasureSpec(100, MeasureSpec.UNSPECIFIED)), 362 eq(MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY))); 363 } 364 365 @UiThreadTest 366 @Test 367 public void testMeasureSpecsWithPadding() { 368 MyView child = spy(new MyView(mActivity)); 369 mScrollViewCustomEmpty.setPadding(3, 5, 7, 11); 370 mScrollViewCustomEmpty.addView(child); 371 372 mScrollViewCustomEmpty.measureChild(child, 373 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 374 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY)); 375 verify(child).onMeasure( 376 eq(MeasureSpec.makeMeasureSpec(90, MeasureSpec.UNSPECIFIED)), 377 eq(MeasureSpec.makeMeasureSpec(134, MeasureSpec.EXACTLY))); 378 } 379 380 @UiThreadTest 381 @Test 382 public void testMeasureSpecsWithMargins() { 383 MyView child = spy(new MyView(mActivity)); 384 mScrollViewCustomEmpty.addView(child); 385 386 mScrollViewCustomEmpty.measureChildWithMargins(child, 387 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 15, 388 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20); 389 verify(child).onMeasure( 390 eq(MeasureSpec.makeMeasureSpec(85, MeasureSpec.UNSPECIFIED)), 391 eq(MeasureSpec.makeMeasureSpec(130, MeasureSpec.EXACTLY))); 392 } 393 394 @UiThreadTest 395 @Test 396 public void testMeasureSpecsWithMarginsAndPadding() { 397 MyView child = spy(new MyView(mActivity)); 398 mScrollViewCustomEmpty.setPadding(3, 5, 7, 11); 399 mScrollViewCustomEmpty.addView(child); 400 401 mScrollViewCustomEmpty.measureChildWithMargins(child, 402 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 15, 403 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20); 404 verify(child).onMeasure( 405 eq(MeasureSpec.makeMeasureSpec(75, MeasureSpec.UNSPECIFIED)), 406 eq(MeasureSpec.makeMeasureSpec(114, MeasureSpec.EXACTLY))); 407 } 408 409 @UiThreadTest 410 @Test 411 public void testMeasureSpecsWithMarginsAndNoHintWidth() { 412 MyView child = spy(new MyView(mActivity)); 413 mScrollViewCustomEmpty.addView(child); 414 415 mScrollViewCustomEmpty.measureChildWithMargins(child, 416 MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 15, 417 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20); 418 verify(child).onMeasure( 419 eq(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)), 420 eq(MeasureSpec.makeMeasureSpec(130, MeasureSpec.EXACTLY))); 421 } 422 423 @UiThreadTest 424 @Test 425 public void testFillViewport() { 426 MyView child = new MyView(mActivity); 427 mScrollViewRegular.setFillViewport(true); 428 child.setLayoutParams(new ViewGroup.LayoutParams( 429 ViewGroup.LayoutParams.WRAP_CONTENT, 430 ViewGroup.LayoutParams.WRAP_CONTENT 431 )); 432 433 mScrollViewRegular.addView(child); 434 mScrollViewRegular.measure(MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 435 MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY)); 436 437 assertEquals(150, child.getMeasuredWidth()); 438 assertEquals(100, child.getMeasuredHeight()); 439 440 mScrollViewRegular.layout(0, 0, 150, 100); 441 assertEquals(0, child.getLeft()); 442 } 443 444 @UiThreadTest 445 @Test 446 public void testFillViewportWithScrollViewPadding() { 447 mScrollViewRegular.setFillViewport(true); 448 mScrollViewRegular.setPadding(3, 10, 5, 7); 449 450 MyView child = new MyView(mActivity); 451 child.setLayoutParams(new ViewGroup.LayoutParams(10,10)); 452 child.setDesiredWidth(30); 453 454 mScrollViewRegular.addView(child); 455 mScrollViewRegular.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 456 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY)); 457 458 assertEquals(92, child.getMeasuredWidth()); 459 assertEquals(10, child.getMeasuredHeight()); 460 461 mScrollViewRegular.layout(0, 0, 100, 150); 462 assertEquals(3, child.getLeft()); 463 } 464 465 @UiThreadTest 466 @Test 467 public void testFillViewportWithChildMargins() { 468 mScrollViewRegular.setFillViewport(true); 469 470 MyView child = new MyView(mActivity); 471 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(10, 10); 472 lp.leftMargin = 3; 473 lp.topMargin = 10; 474 lp.rightMargin = 5; 475 lp.bottomMargin = 7; 476 child.setDesiredWidth(30); 477 child.setLayoutParams(lp); 478 479 mScrollViewRegular.addView(child); 480 mScrollViewRegular.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 481 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY)); 482 483 assertEquals(92, child.getMeasuredWidth()); 484 assertEquals(10, child.getMeasuredHeight()); 485 486 mScrollViewRegular.layout(0, 0, 100, 150); 487 assertEquals(3, child.getLeft()); 488 } 489 490 @UiThreadTest 491 @Test 492 public void testFillViewportWithScrollViewPaddingAlreadyFills() { 493 mScrollViewRegular.setFillViewport(true); 494 mScrollViewRegular.setPadding(3, 10, 5, 7); 495 496 MyView child = new MyView(mActivity); 497 child.setDesiredWidth(175); 498 499 mScrollViewRegular.addView(child); 500 mScrollViewRegular.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 501 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY)); 502 503 504 assertEquals(175, child.getMeasuredWidth()); 505 assertEquals(133, child.getMeasuredHeight()); 506 507 mScrollViewRegular.layout(0, 0, 100, 150); 508 assertEquals(3, child.getLeft()); 509 } 510 511 @UiThreadTest 512 @Test 513 public void testFillViewportWithChildMarginsAlreadyFills() { 514 mScrollViewRegular.setFillViewport(true); 515 MyView child = new MyView(mActivity); 516 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( 517 ViewGroup.LayoutParams.MATCH_PARENT, 518 ViewGroup.LayoutParams.WRAP_CONTENT); 519 520 lp.leftMargin = 3; 521 lp.topMargin = 10; 522 lp.rightMargin = 5; 523 lp.bottomMargin = 7; 524 child.setLayoutParams(lp); 525 child.setDesiredWidth(175); 526 527 mScrollViewRegular.addView(child); 528 mScrollViewRegular.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 529 MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY)); 530 531 assertEquals(175, child.getMeasuredWidth()); 532 assertEquals(133, child.getMeasuredHeight()); 533 534 mScrollViewRegular.layout(0, 0, 100, 150); 535 assertEquals(3, child.getLeft()); 536 } 537 538 @UiThreadTest 539 @Test 540 public void testPageScroll() { 541 mScrollViewCustom.setSmoothScrollingEnabled(false); 542 assertEquals(0, mScrollViewCustom.getScrollX()); 543 544 assertTrue(mScrollViewCustom.pageScroll(View.FOCUS_RIGHT)); 545 assertEquals(PAGE_WIDTH, mScrollViewCustom.getScrollX()); 546 547 mScrollViewCustom.scrollTo(SCROLL_RIGHT, PAGE_HEIGHT); 548 assertFalse(mScrollViewCustom.pageScroll(View.FOCUS_RIGHT)); 549 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 550 551 assertTrue(mScrollViewCustom.pageScroll(View.FOCUS_LEFT)); 552 assertEquals(SCROLL_RIGHT - PAGE_WIDTH, mScrollViewCustom.getScrollX()); 553 554 mScrollViewCustom.scrollTo(0, PAGE_HEIGHT); 555 assertFalse(mScrollViewCustom.pageScroll(View.FOCUS_LEFT)); 556 assertEquals(0, mScrollViewCustom.getScrollX()); 557 } 558 559 @UiThreadTest 560 @Test 561 public void testFullScroll() { 562 mScrollViewCustom.setSmoothScrollingEnabled(false); 563 assertEquals(0, mScrollViewCustom.getScrollX()); 564 565 assertTrue(mScrollViewCustom.fullScroll(View.FOCUS_RIGHT)); 566 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 567 568 assertFalse(mScrollViewCustom.fullScroll(View.FOCUS_RIGHT)); 569 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 570 571 assertTrue(mScrollViewCustom.fullScroll(View.FOCUS_LEFT)); 572 assertEquals(0, mScrollViewCustom.getScrollX()); 573 574 assertFalse(mScrollViewCustom.fullScroll(View.FOCUS_LEFT)); 575 assertEquals(0, mScrollViewCustom.getScrollX()); 576 } 577 578 @UiThreadTest 579 @Test 580 public void testArrowScroll() { 581 mScrollViewCustom.setSmoothScrollingEnabled(false); 582 assertEquals(0, mScrollViewCustom.getScrollX()); 583 584 int x = mScrollViewCustom.getScrollX(); 585 while (SCROLL_RIGHT != x) { 586 assertTrue(mScrollViewCustom.arrowScroll(View.FOCUS_RIGHT)); 587 assertTrue(x <= mScrollViewCustom.getScrollX()); 588 x = mScrollViewCustom.getScrollX(); 589 } 590 591 assertFalse(mScrollViewCustom.arrowScroll(View.FOCUS_RIGHT)); 592 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 593 594 x = mScrollViewCustom.getScrollX(); 595 while (0 != x) { 596 assertTrue(mScrollViewCustom.arrowScroll(View.FOCUS_LEFT)); 597 assertTrue(x >= mScrollViewCustom.getScrollX()); 598 x = mScrollViewCustom.getScrollX(); 599 } 600 601 assertFalse(mScrollViewCustom.arrowScroll(View.FOCUS_LEFT)); 602 assertEquals(0, mScrollViewCustom.getScrollX()); 603 } 604 605 @Test 606 public void testSmoothScrollBy() throws Throwable { 607 assertEquals(0, mScrollViewCustom.getScrollX()); 608 assertEquals(0, mScrollViewCustom.getScrollY()); 609 610 mActivityRule.runOnUiThread(() -> mScrollViewCustom.smoothScrollBy(SCROLL_RIGHT, 0)); 611 pollingCheckSmoothScrolling(0, SCROLL_RIGHT, 0, 0); 612 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 613 assertEquals(0, mScrollViewCustom.getScrollY()); 614 615 mActivityRule.runOnUiThread(() -> mScrollViewCustom.smoothScrollBy(-SCROLL_RIGHT, 0)); 616 pollingCheckSmoothScrolling(SCROLL_RIGHT, 0, 0, 0); 617 assertEquals(0, mScrollViewCustom.getScrollX()); 618 assertEquals(0, mScrollViewCustom.getScrollY()); 619 } 620 621 @Test 622 public void testSmoothScrollTo() throws Throwable { 623 assertEquals(0, mScrollViewCustom.getScrollX()); 624 assertEquals(0, mScrollViewCustom.getScrollY()); 625 626 mActivityRule.runOnUiThread(() -> mScrollViewCustom.smoothScrollTo(SCROLL_RIGHT, 0)); 627 pollingCheckSmoothScrolling(0, SCROLL_RIGHT, 0, 0); 628 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 629 assertEquals(0, mScrollViewCustom.getScrollY()); 630 631 mActivityRule.runOnUiThread(() -> mScrollViewCustom.smoothScrollTo(0, 0)); 632 pollingCheckSmoothScrolling(SCROLL_RIGHT, 0, 0, 0); 633 assertEquals(0, mScrollViewCustom.getScrollX()); 634 assertEquals(0, mScrollViewCustom.getScrollY()); 635 } 636 637 @Test 638 public void testComputeScrollDeltaToGetChildRectOnScreen() { 639 mScrollViewCustom.setSmoothScrollingEnabled(false); 640 int edge = mScrollViewCustom.getHorizontalFadingEdgeLength(); 641 642 MyHorizontalScrollView myScrollViewCustom = (MyHorizontalScrollView) mScrollViewCustom; 643 644 // Rect's width is smaller than scroll view 645 Rect rect = new Rect(0, 0, 0, 0); 646 assertEquals(0, myScrollViewCustom.computeScrollDeltaToGetChildRectOnScreen(rect)); 647 648 rect = new Rect(edge, 0, PAGE_WIDTH, 0); 649 assertEquals(0, myScrollViewCustom.computeScrollDeltaToGetChildRectOnScreen(rect)); 650 651 mScrollViewCustom.scrollTo(0, 0); 652 rect = new Rect(edge + 1, 0, PAGE_WIDTH, 0); 653 assertEquals(edge, myScrollViewCustom.computeScrollDeltaToGetChildRectOnScreen(rect)); 654 } 655 656 @Test 657 public void testComputeHorizontalScrollRange() { 658 assertTrue(mScrollViewCustom.getChildCount() > 0); 659 assertEquals(ITEM_WIDTH * ITEM_COUNT, 660 ((MyHorizontalScrollView) mScrollViewCustom).computeHorizontalScrollRange()); 661 662 MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity); 663 assertEquals(0, scrollView.getChildCount()); 664 assertEquals(0, scrollView.computeHorizontalScrollRange()); 665 } 666 667 @UiThreadTest 668 @Test 669 public void testRequestChildFocus() { 670 mScrollViewCustom.setSmoothScrollingEnabled(false); 671 672 View firstChild = mScrollViewCustom.findViewById(R.id.first_horizontal_child); 673 View lastChild = mScrollViewCustom.findViewById(R.id.last_horizontal_child); 674 firstChild.requestFocus(); 675 676 int scrollX = mScrollViewCustom.getScrollX(); 677 mScrollViewCustom.requestChildFocus(lastChild, lastChild); 678 // check scrolling to the child which wants focus 679 assertTrue(mScrollViewCustom.getScrollX() > scrollX); 680 681 scrollX = mScrollViewCustom.getScrollX(); 682 mScrollViewCustom.requestChildFocus(firstChild, firstChild); 683 // check scrolling to the child which wants focus 684 assertTrue(mScrollViewCustom.getScrollX() < scrollX); 685 } 686 687 @UiThreadTest 688 @Test 689 public void testRequestChildRectangleOnScreen() { 690 mScrollViewCustom.setSmoothScrollingEnabled(false); 691 int edge = mScrollViewCustom.getHorizontalFadingEdgeLength(); 692 693 View child = mScrollViewCustom.findViewById(R.id.first_horizontal_child); 694 final Rect originalRect = new Rect(0, 0, 10, 10); 695 final Rect newRect = new Rect(ITEM_WIDTH - 10, ITEM_HEIGHT - 10, ITEM_WIDTH, ITEM_HEIGHT); 696 697 assertFalse(mScrollViewCustom.requestChildRectangleOnScreen(child, originalRect, true)); 698 assertEquals(0, mScrollViewCustom.getScrollX()); 699 assertEquals(0, mScrollViewCustom.getScrollY()); 700 701 assertTrue(mScrollViewCustom.requestChildRectangleOnScreen(child, newRect, true)); 702 assertEquals(ITEM_WIDTH - mScrollViewCustom.getWidth() + edge, mScrollViewCustom.getScrollX()); 703 assertEquals(0, mScrollViewCustom.getScrollY()); 704 } 705 706 @UiThreadTest 707 @Test 708 public void testRequestLayout() { 709 mScrollViewCustom.requestLayout(); 710 711 assertTrue(mScrollViewCustom.isLayoutRequested()); 712 } 713 714 @Test 715 public void testFling() throws Throwable { 716 mScrollViewCustom.setSmoothScrollingEnabled(true); 717 assertEquals(0, mScrollViewCustom.getScrollX()); 718 719 final int velocityX = WidgetTestUtils.convertDipToPixels(mActivity, 2000); 720 721 // fling towards right 722 mActivityRule.runOnUiThread(() -> mScrollViewCustom.fling(velocityX)); 723 pollingCheckFling(0, true); 724 725 final int currentX = mScrollViewCustom.getScrollX(); 726 // fling towards left 727 mActivityRule.runOnUiThread(() -> mScrollViewCustom.fling(-velocityX)); 728 pollingCheckFling(currentX, false); 729 } 730 731 @UiThreadTest 732 @Test 733 public void testScrollTo() { 734 mScrollViewCustom.setSmoothScrollingEnabled(false); 735 736 mScrollViewCustom.scrollTo(10, 10); 737 assertEquals(0, mScrollViewCustom.getScrollY()); 738 assertEquals(10, mScrollViewCustom.getScrollX()); 739 740 mScrollViewCustom.scrollTo(PAGE_WIDTH, PAGE_HEIGHT); 741 assertEquals(0, mScrollViewCustom.getScrollY()); 742 assertEquals(PAGE_WIDTH, mScrollViewCustom.getScrollX()); 743 744 mScrollViewCustom.scrollTo(SCROLL_RIGHT, 0); 745 assertEquals(0, mScrollViewCustom.getScrollY()); 746 assertEquals(SCROLL_RIGHT, mScrollViewCustom.getScrollX()); 747 748 // reach the top and left 749 mScrollViewCustom.scrollTo(-10, -10); 750 assertEquals(0, mScrollViewCustom.getScrollY()); 751 assertEquals(0, mScrollViewCustom.getScrollX()); 752 } 753 754 @Test 755 public void testGetHorizontalFadingEdgeStrengths() { 756 MyHorizontalScrollView myScrollViewCustom = (MyHorizontalScrollView) mScrollViewCustom; 757 758 assertTrue(mScrollViewCustom.getChildCount() > 0); 759 assertTrue(myScrollViewCustom.getLeftFadingEdgeStrength() <= 1.0f); 760 assertTrue(myScrollViewCustom.getLeftFadingEdgeStrength() >= 0.0f); 761 assertTrue(myScrollViewCustom.getRightFadingEdgeStrength() <= 1.0f); 762 assertTrue(myScrollViewCustom.getRightFadingEdgeStrength() >= 0.0f); 763 764 MyHorizontalScrollView myScrollView = new MyHorizontalScrollView(mActivity); 765 assertEquals(0, myScrollView.getChildCount()); 766 assertTrue(myScrollViewCustom.getLeftFadingEdgeStrength() <= 1.0f); 767 assertTrue(myScrollViewCustom.getLeftFadingEdgeStrength() >= 0.0f); 768 assertTrue(myScrollViewCustom.getRightFadingEdgeStrength() <= 1.0f); 769 assertTrue(myScrollViewCustom.getRightFadingEdgeStrength() >= 0.0f); 770 } 771 772 private boolean isInRange(int current, int from, int to) { 773 if (from < to) { 774 return current >= from && current <= to; 775 } 776 return current <= from && current >= to; 777 } 778 779 private void pollingCheckSmoothScrolling(final int fromX, final int toX, 780 final int fromY, final int toY) { 781 782 if (fromX == toX && fromY == toY) { 783 return; 784 } 785 786 if (fromY != toY) { 787 PollingCheck.waitFor(() -> isInRange(mScrollViewCustom.getScrollY(), fromY, toY)); 788 } 789 790 if (fromX != toX) { 791 PollingCheck.waitFor(() -> isInRange(mScrollViewCustom.getScrollX(), fromX, toX)); 792 } 793 794 PollingCheck.waitFor( 795 () -> toX == mScrollViewCustom.getScrollX() && toY == mScrollViewCustom.getScrollY()); 796 } 797 798 private void pollingCheckFling(final int startPosition, final boolean movingRight) { 799 PollingCheck.waitFor(() -> { 800 if (movingRight) { 801 return mScrollViewCustom.getScrollX() > startPosition; 802 } 803 return mScrollViewCustom.getScrollX() < startPosition; 804 }); 805 806 final int[] previousScrollX = new int[] { mScrollViewCustom.getScrollX() }; 807 PollingCheck.waitFor(() -> { 808 if (mScrollViewCustom.getScrollX() == previousScrollX[0]) { 809 return true; 810 } else { 811 previousScrollX[0] = mScrollViewCustom.getScrollX(); 812 return false; 813 } 814 }); 815 } 816 817 public static class MyView extends View { 818 // measure in this height if set 819 private Integer mDesiredWidth; 820 public MyView(Context context) { 821 super(context); 822 } 823 824 public void setDesiredWidth(Integer desiredWidth) { 825 mDesiredWidth = desiredWidth; 826 } 827 828 @Override 829 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 830 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 831 if (mDesiredWidth != null) { 832 int mode = MeasureSpec.getMode(widthMeasureSpec); 833 int size = MeasureSpec.getSize(widthMeasureSpec); 834 int newWidth = size; 835 if (mode == MeasureSpec.AT_MOST) { 836 newWidth = Math.max(size, mDesiredWidth); 837 } else if (mode == MeasureSpec.UNSPECIFIED) { 838 newWidth = mDesiredWidth; 839 } 840 setMeasuredDimension(newWidth, getMeasuredHeight()); 841 } 842 } 843 } 844 845 public static class MyHorizontalScrollView extends HorizontalScrollView { 846 public MyHorizontalScrollView(Context context) { 847 super(context); 848 } 849 850 public MyHorizontalScrollView(Context context, AttributeSet attrs) { 851 super(context, attrs); 852 } 853 854 public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { 855 super(context, attrs, defStyle); 856 } 857 858 @Override 859 protected int computeHorizontalScrollRange() { 860 return super.computeHorizontalScrollRange(); 861 } 862 863 @Override 864 protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) { 865 return super.computeScrollDeltaToGetChildRectOnScreen(rect); 866 } 867 868 @Override 869 protected float getLeftFadingEdgeStrength() { 870 return super.getLeftFadingEdgeStrength(); 871 } 872 873 @Override 874 protected float getRightFadingEdgeStrength() { 875 return super.getRightFadingEdgeStrength(); 876 } 877 878 @Override 879 protected void measureChild(View child, int parentWidthMeasureSpec, 880 int parentHeightMeasureSpec) { 881 super.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec); 882 } 883 884 @Override 885 protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, 886 int parentHeightMeasureSpec, int heightUsed) { 887 super.measureChildWithMargins(child, parentWidthMeasureSpec, 888 widthUsed, parentHeightMeasureSpec, heightUsed); 889 } 890 891 @Override 892 public int computeVerticalScrollRange() { 893 return super.computeVerticalScrollRange(); 894 } 895 896 @Override 897 public int computeVerticalScrollOffset() { 898 return super.computeVerticalScrollOffset(); 899 } 900 901 @Override 902 public int computeVerticalScrollExtent() { 903 return super.computeVerticalScrollExtent(); 904 } 905 } 906 } 907