1/* 2 * Copyright 2018 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 17package androidx.core.widget; 18 19import static org.hamcrest.CoreMatchers.is; 20import static org.hamcrest.MatcherAssert.assertThat; 21import static org.mockito.ArgumentMatchers.any; 22import static org.mockito.ArgumentMatchers.anyInt; 23import static org.mockito.ArgumentMatchers.eq; 24import static org.mockito.Mockito.doReturn; 25import static org.mockito.Mockito.never; 26import static org.mockito.Mockito.spy; 27import static org.mockito.Mockito.times; 28import static org.mockito.Mockito.verify; 29 30import android.content.Context; 31import android.support.test.filters.SmallTest; 32import android.support.test.runner.AndroidJUnit4; 33import android.support.v4.BaseInstrumentationTestCase; 34import android.view.View; 35import android.view.ViewGroup; 36import android.widget.FrameLayout; 37 38import androidx.annotation.NonNull; 39import androidx.annotation.Nullable; 40import androidx.core.test.R; 41import androidx.core.view.NestedScrollingChild2; 42import androidx.core.view.NestedScrollingParent2; 43import androidx.core.view.ViewCompat; 44 45import org.junit.Before; 46import org.junit.Test; 47import org.junit.runner.RunWith; 48 49/** 50 * So far these tests only cover {@code NestedScrollView}'s implementation of 51 * {@link NestedScrollingParent2} and the backwards compatibility of {@code NestedScrollView}'s 52 * implementation of {@link androidx.core.view.NestedScrollingParent} for the methods that 53 * {@link NestedScrollingParent2} overloads. 54 */ 55 56@RunWith(AndroidJUnit4.class) 57@SmallTest 58public class NestedScrollViewNestedScrollingParentTest extends 59 BaseInstrumentationTestCase<TestContentViewActivity> { 60 61 private NestedScrollView mNestedScrollView; 62 private NestedScrollingSpyView mParent; 63 private View mChild; 64 65 public NestedScrollViewNestedScrollingParentTest() { 66 super(TestContentViewActivity.class); 67 } 68 69 @Before 70 public void instantiateMembers() { 71 mNestedScrollView = new NestedScrollView(mActivityTestRule.getActivity()); 72 mParent = spy(new NestedScrollingSpyView(mActivityTestRule.getActivity())); 73 mChild = new View(mActivityTestRule.getActivity()); 74 } 75 76 @Test 77 public void onStartNestedScroll_scrollAxisIncludesVertical_alwaysReturnsTrue() { 78 int vertical = ViewCompat.SCROLL_AXIS_VERTICAL; 79 int both = ViewCompat.SCROLL_AXIS_VERTICAL | ViewCompat.SCROLL_AXIS_HORIZONTAL; 80 81 onStartNestedScrollV1(vertical, true); 82 onStartNestedScrollV1(both, true); 83 84 onStartNestedScrollV2(vertical, true); 85 onStartNestedScrollV2(both, true); 86 } 87 88 @Test 89 public void onStartNestedScroll_scrollAxisExcludesVertical_alwaysReturnsFalse() { 90 int horizontal = ViewCompat.SCROLL_AXIS_HORIZONTAL; 91 int neither = ViewCompat.SCROLL_AXIS_NONE; 92 93 onStartNestedScrollV1(horizontal, false); 94 onStartNestedScrollV1(neither, false); 95 96 onStartNestedScrollV2(horizontal, false); 97 onStartNestedScrollV2(neither, false); 98 } 99 100 @Test 101 public void onNestedScrollAccepted_callsParentsOnStartNestedScrollWithCorrectParams() 102 throws Throwable { 103 setupNestedScrollViewWithParentAndChild(); 104 mActivityTestRule.runOnUiThread(new Runnable() { 105 @Override 106 public void run() { 107 108 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 109 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 110 111 verify(mParent).onStartNestedScroll(mNestedScrollView, mNestedScrollView, 112 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 113 } 114 }); 115 } 116 117 @Test 118 public void onNestedScrollAccepted_callsParentsOnNestedScrollAcceptedWithCorrectParams() 119 throws Throwable { 120 setupNestedScrollViewWithParentAndChild(); 121 mActivityTestRule.runOnUiThread(new Runnable() { 122 @Override 123 public void run() { 124 doReturn(true) 125 .when(mParent) 126 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 127 128 mNestedScrollView.onNestedScrollAccepted( 129 mChild, 130 mChild, 131 ViewCompat.SCROLL_AXIS_VERTICAL, 132 ViewCompat.TYPE_NON_TOUCH); 133 134 verify(mParent, times(1)).onNestedScrollAccepted( 135 mNestedScrollView, 136 mNestedScrollView, 137 ViewCompat.SCROLL_AXIS_VERTICAL, 138 ViewCompat.TYPE_NON_TOUCH); 139 verify(mParent, times(1)).onNestedScrollAccepted( 140 any(View.class), 141 any(View.class), 142 anyInt(), 143 anyInt()); 144 } 145 }); 146 } 147 148 @Test 149 public void onNestedScrollAccepted_withBothOrientations_pOnNestedScrollAcceptedCalledWithVert() 150 throws Throwable { 151 setupNestedScrollViewWithParentAndChild(); 152 mActivityTestRule.runOnUiThread(new Runnable() { 153 @Override 154 public void run() { 155 doReturn(true) 156 .when(mParent) 157 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 158 159 mNestedScrollView.onNestedScrollAccepted( 160 mChild, 161 mChild, 162 ViewCompat.SCROLL_AXIS_VERTICAL | ViewCompat.SCROLL_AXIS_HORIZONTAL, 163 ViewCompat.TYPE_NON_TOUCH); 164 165 verify(mParent, times(1)).onNestedScrollAccepted( 166 any(View.class), 167 any(View.class), 168 eq(ViewCompat.SCROLL_AXIS_VERTICAL), 169 anyInt()); 170 verify(mParent, times(1)).onNestedScrollAccepted( 171 any(View.class), 172 any(View.class), 173 anyInt(), 174 anyInt()); 175 176 } 177 }); 178 } 179 180 @Test 181 public void onNestedScrollAccepted_parentRejects_parentOnNestedScrollAcceptedNotCalled() 182 throws Throwable { 183 setupNestedScrollViewWithParentAndChild(); 184 mActivityTestRule.runOnUiThread(new Runnable() { 185 @Override 186 public void run() { 187 doReturn(false) 188 .when(mParent) 189 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 190 191 mNestedScrollView.onNestedScrollAccepted( 192 mChild, 193 mChild, 194 ViewCompat.SCROLL_AXIS_VERTICAL, 195 ViewCompat.TYPE_TOUCH); 196 197 verify(mParent, never()).onNestedScrollAccepted( 198 any(View.class), 199 any(View.class), 200 anyInt(), 201 anyInt()); 202 } 203 }); 204 } 205 206 @Test 207 public void onNestedScrollAccepted_v1_callsParentWithTypeTouch() throws Throwable { 208 setupNestedScrollViewWithParentAndChild(); 209 mActivityTestRule.runOnUiThread(new Runnable() { 210 @Override 211 public void run() { 212 doReturn(true) 213 .when(mParent) 214 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 215 216 mNestedScrollView.onNestedScrollAccepted( 217 mChild, 218 mChild, 219 ViewCompat.SCROLL_AXIS_VERTICAL); 220 221 verify(mParent, times(1)).onNestedScrollAccepted( 222 any(View.class), 223 any(View.class), 224 anyInt(), 225 eq(ViewCompat.TYPE_TOUCH)); 226 verify(mParent, times(1)).onNestedScrollAccepted( 227 any(View.class), 228 any(View.class), 229 anyInt(), 230 anyInt()); 231 } 232 }); 233 } 234 235 @Test 236 public void onStopNestedScroll_parentOnStopNestedScrollCalledWithCorrectParams() 237 throws Throwable { 238 setupNestedScrollViewWithParentAndChild(); 239 mActivityTestRule.runOnUiThread(new Runnable() { 240 @Override 241 public void run() { 242 doReturn(true) 243 .when(mParent) 244 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 245 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 246 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 247 248 mNestedScrollView.onStopNestedScroll(mChild, ViewCompat.TYPE_NON_TOUCH); 249 250 verify(mParent, times(1)).onStopNestedScroll(mNestedScrollView, 251 ViewCompat.TYPE_NON_TOUCH); 252 verify(mParent, times(1)).onStopNestedScroll(any(View.class), anyInt()); 253 } 254 }); 255 } 256 257 // TODO(shepshapard), test with interactions where scroll type changes. 258 259 @Test 260 public void onStopNestedScroll_parentRejects_parentOnStopNestedScrollNotCalled() 261 throws Throwable { 262 setupNestedScrollViewWithParentAndChild(); 263 mActivityTestRule.runOnUiThread(new Runnable() { 264 @Override 265 public void run() { 266 doReturn(false) 267 .when(mParent) 268 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 269 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 270 ViewCompat.SCROLL_AXIS_VERTICAL); 271 272 mNestedScrollView.onStopNestedScroll(mChild, ViewCompat.TYPE_NON_TOUCH); 273 274 verify(mParent, never()).onStopNestedScroll(any(View.class), anyInt()); 275 } 276 }); 277 } 278 279 @Test 280 public void onStopNestedScroll_calledWithTypeNotYetAccepted_parentOnStopNestedScrollNotCalled() 281 throws Throwable { 282 setupNestedScrollViewWithParentAndChild(); 283 mActivityTestRule.runOnUiThread(new Runnable() { 284 @Override 285 public void run() { 286 doReturn(true) 287 .when(mParent) 288 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 289 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 290 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_TOUCH); 291 292 mNestedScrollView.onStopNestedScroll(mChild, ViewCompat.TYPE_NON_TOUCH); 293 294 verify(mParent, never()).onStopNestedScroll(any(View.class), anyInt()); 295 } 296 }); 297 } 298 299 @Test 300 public void onStopNestedScroll_v1_parentOnStopNestedScrollCalledWithTypeTouch() 301 throws Throwable { 302 setupNestedScrollViewWithParentAndChild(); 303 mActivityTestRule.runOnUiThread(new Runnable() { 304 @Override 305 public void run() { 306 doReturn(true) 307 .when(mParent) 308 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 309 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 310 ViewCompat.SCROLL_AXIS_VERTICAL); 311 312 mNestedScrollView.onStopNestedScroll(mChild); 313 314 verify(mParent, times(1)).onStopNestedScroll(any(View.class), 315 eq(ViewCompat.TYPE_TOUCH)); 316 verify(mParent, times(1)).onStopNestedScroll(any(View.class), anyInt()); 317 } 318 }); 319 } 320 321 @Test 322 public void onNestedScroll_nsvScrolls() throws Throwable { 323 setupNestedScrollViewWithParentAndChild(50, 100); 324 mActivityTestRule.runOnUiThread(new Runnable() { 325 @Override 326 public void run() { 327 328 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, 50, ViewCompat.TYPE_NON_TOUCH); 329 330 assertThat(mNestedScrollView.getScrollY(), is(50)); 331 } 332 }); 333 } 334 335 @Test 336 public void onNestedScroll_negativeScroll_nsvScrollsNegative() throws Throwable { 337 setupNestedScrollViewWithParentAndChild(50, 100); 338 mActivityTestRule.runOnUiThread(new Runnable() { 339 @Override 340 public void run() { 341 mNestedScrollView.scrollTo(0, 50); 342 343 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, -50, ViewCompat.TYPE_NON_TOUCH); 344 345 assertThat(mNestedScrollView.getScrollY(), is(0)); 346 } 347 }); 348 } 349 350 @Test 351 public void onNestedScroll_nsvConsumesEntireScroll_correctScrollDistancesPastToParent() 352 throws Throwable { 353 setupNestedScrollViewWithParentAndChild(50, 100); 354 mActivityTestRule.runOnUiThread(new Runnable() { 355 @Override 356 public void run() { 357 doReturn(true) 358 .when(mParent) 359 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 360 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 361 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 362 363 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, 50, ViewCompat.TYPE_NON_TOUCH); 364 365 verify(mParent, times(1)).onNestedScroll(any(View.class), eq(0), eq(50), eq(0), 366 eq(0), anyInt()); 367 verify(mParent, times(1)).onNestedScroll(any(View.class), anyInt(), anyInt(), 368 anyInt(), anyInt(), anyInt()); 369 } 370 }); 371 } 372 373 @Test 374 public void onNestedScroll_nsvCanOnlyConsumePartOfScroll_correctScrollDistancesPastToParent() 375 throws Throwable { 376 setupNestedScrollViewWithParentAndChild(50, 100); 377 mActivityTestRule.runOnUiThread(new Runnable() { 378 @Override 379 public void run() { 380 doReturn(true) 381 .when(mParent) 382 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 383 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 384 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 385 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, 75, ViewCompat.TYPE_NON_TOUCH); 386 387 verify(mParent, times(1)).onNestedScroll(any(View.class), eq(0), eq(50), eq(0), 388 eq(25), anyInt()); 389 verify(mParent, times(1)).onNestedScroll(any(View.class), anyInt(), anyInt(), 390 anyInt(), anyInt(), anyInt()); 391 } 392 }); 393 } 394 395 @Test 396 public void onNestedScroll_nsvCanOnlyConsumePartOfScrollNeg_correctScrollDistancesPastToParent() 397 throws Throwable { 398 setupNestedScrollViewWithParentAndChild(50, 100); 399 mActivityTestRule.runOnUiThread(new Runnable() { 400 @Override 401 public void run() { 402 doReturn(true) 403 .when(mParent) 404 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 405 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 406 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 407 mNestedScrollView.scrollTo(0, 50); 408 409 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, -75, ViewCompat.TYPE_NON_TOUCH); 410 411 verify(mParent, times(1)).onNestedScroll(any(View.class), eq(0), eq(-50), eq(0), 412 eq(-25), anyInt()); 413 verify(mParent, times(1)).onNestedScroll(any(View.class), anyInt(), anyInt(), 414 anyInt(), anyInt(), anyInt()); 415 } 416 }); 417 } 418 419 @Test 420 public void onNestedScroll_nsvIsAtEndOfScroll_correctScrollDistancesPastToParent() 421 throws Throwable { 422 setupNestedScrollViewWithParentAndChild(50, 100); 423 mActivityTestRule.runOnUiThread(new Runnable() { 424 @Override 425 public void run() { 426 doReturn(true) 427 .when(mParent) 428 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 429 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 430 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 431 mNestedScrollView.scrollTo(0, 50); 432 433 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, 50, ViewCompat.TYPE_NON_TOUCH); 434 435 verify(mParent, times(1)).onNestedScroll(any(View.class), eq(0), eq(0), eq(0), 436 eq(50), anyInt()); 437 verify(mParent, times(1)).onNestedScroll(any(View.class), anyInt(), anyInt(), 438 anyInt(), anyInt(), anyInt()); 439 } 440 }); 441 } 442 443 @Test 444 public void onNestedScroll_parentRejects_parentOnNestedScrollNotCalled() throws Throwable { 445 setupNestedScrollViewWithParentAndChild(50, 100); 446 mActivityTestRule.runOnUiThread(new Runnable() { 447 @Override 448 public void run() { 449 doReturn(false) 450 .when(mParent) 451 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 452 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 453 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 454 455 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, 50, ViewCompat.TYPE_NON_TOUCH); 456 457 verify(mParent, never()).onNestedScroll(any(View.class), anyInt(), anyInt(), 458 anyInt(), anyInt(), anyInt()); 459 } 460 }); 461 } 462 463 @Test 464 public void onNestedScroll_calledWithTypeNotYetAccepted_parentOnStopNestedScrollNotCalled() 465 throws Throwable { 466 setupNestedScrollViewWithParentAndChild(50, 100); 467 mActivityTestRule.runOnUiThread(new Runnable() { 468 @Override 469 public void run() { 470 doReturn(true) 471 .when(mParent) 472 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 473 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 474 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_TOUCH); 475 476 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, 50, ViewCompat.TYPE_NON_TOUCH); 477 478 verify(mParent, never()).onNestedScroll(any(View.class), anyInt(), anyInt(), 479 anyInt(), anyInt(), anyInt()); 480 } 481 }); 482 } 483 484 @Test 485 public void onNestedScroll_v1_parentOnNestedScrollCalledWithTypeTouch() 486 throws Throwable { 487 setupNestedScrollViewWithParentAndChild(50, 100); 488 mActivityTestRule.runOnUiThread(new Runnable() { 489 @Override 490 public void run() { 491 doReturn(true) 492 .when(mParent) 493 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 494 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 495 ViewCompat.SCROLL_AXIS_VERTICAL); 496 497 mNestedScrollView.onNestedScroll(mChild, 0, 0, 0, 50); 498 499 verify(mParent, times(1)).onNestedScroll(any(View.class), anyInt(), anyInt(), 500 anyInt(), anyInt(), eq(ViewCompat.TYPE_TOUCH)); 501 verify(mParent, times(1)).onNestedScroll(any(View.class), anyInt(), anyInt(), 502 anyInt(), anyInt(), anyInt()); 503 } 504 }); 505 } 506 507 @Test 508 public void onNestedPreScroll_parentOnNestedPreScrollCalledWithCorrectParams() 509 throws Throwable { 510 setupNestedScrollViewWithParentAndChild(); 511 mActivityTestRule.runOnUiThread(new Runnable() { 512 @Override 513 public void run() { 514 doReturn(true) 515 .when(mParent) 516 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 517 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 518 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 519 520 mNestedScrollView.onNestedPreScroll(mChild, 1, 2, new int[]{0, 0}, 521 ViewCompat.TYPE_NON_TOUCH); 522 523 verify(mParent, times(1)).onNestedPreScroll(eq(mNestedScrollView), eq(1), eq(2), 524 eq(new int[]{0, 0}), eq(ViewCompat.TYPE_NON_TOUCH)); 525 verify(mParent, times(1)).onNestedPreScroll(any(View.class), anyInt(), anyInt(), 526 any(int[].class), anyInt()); 527 } 528 }); 529 } 530 531 @Test 532 public void onNestedPreScroll_parentRejects_parentOnNestedPreScrollNotCalled() 533 throws Throwable { 534 setupNestedScrollViewWithParentAndChild(); 535 mActivityTestRule.runOnUiThread(new Runnable() { 536 @Override 537 public void run() { 538 doReturn(false) 539 .when(mParent) 540 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 541 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 542 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH); 543 544 mNestedScrollView.onNestedPreScroll(mChild, 1, 2, new int[2], 545 ViewCompat.TYPE_NON_TOUCH); 546 547 verify(mParent, never()).onNestedPreScroll(any(View.class), anyInt(), anyInt(), 548 any(int[].class), anyInt()); 549 } 550 }); 551 } 552 553 @Test 554 public void onNestedPreScroll_calledWithTypeNotYetAccepted_parentOnStopNestedScrollNotCalled() 555 throws Throwable { 556 setupNestedScrollViewWithParentAndChild(); 557 mActivityTestRule.runOnUiThread(new Runnable() { 558 @Override 559 public void run() { 560 doReturn(true) 561 .when(mParent) 562 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 563 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 564 ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_TOUCH); 565 566 mNestedScrollView.onNestedPreScroll(mChild, 1, 2, new int[2], 567 ViewCompat.TYPE_NON_TOUCH); 568 569 verify(mParent, never()).onNestedPreScroll(any(View.class), anyInt(), anyInt(), 570 any(int[].class), anyInt()); 571 } 572 }); 573 } 574 575 @Test 576 public void onNestedPreScroll_v1_parentOnNestedPreScrollCalledWithTypeTouch() throws Throwable { 577 setupNestedScrollViewWithParentAndChild(); 578 mActivityTestRule.runOnUiThread(new Runnable() { 579 @Override 580 public void run() { 581 doReturn(true) 582 .when(mParent) 583 .onStartNestedScroll(any(View.class), any(View.class), anyInt(), anyInt()); 584 mNestedScrollView.onNestedScrollAccepted(mChild, mChild, 585 ViewCompat.SCROLL_AXIS_VERTICAL); 586 int[] consumed = new int[2]; 587 588 mNestedScrollView.onNestedPreScroll(mChild, 1, 2, consumed); 589 590 verify(mParent, times(1)).onNestedPreScroll(any(View.class), anyInt(), anyInt(), 591 any(int[].class), eq(ViewCompat.TYPE_TOUCH)); 592 verify(mParent, times(1)).onNestedPreScroll(any(View.class), anyInt(), anyInt(), 593 any(int[].class), anyInt()); 594 } 595 }); 596 } 597 598 private void onStartNestedScrollV1(int iScrollAxis, boolean oRetValue) { 599 boolean retVal = mNestedScrollView.onStartNestedScroll(mChild, mChild, iScrollAxis); 600 assertThat(retVal, is(oRetValue)); 601 } 602 603 private void onStartNestedScrollV2(int iScrollAxis, boolean oRetValue) { 604 boolean retVal = mNestedScrollView.onStartNestedScroll(mChild, mChild, iScrollAxis, 605 ViewCompat.TYPE_TOUCH); 606 assertThat(retVal, is(oRetValue)); 607 } 608 609 private void setupNestedScrollViewWithParentAndChild() throws Throwable { 610 setupNestedScrollViewWithParentAndChild(ViewGroup.LayoutParams.MATCH_PARENT, 611 ViewGroup.LayoutParams.MATCH_PARENT); 612 } 613 614 private void setupNestedScrollViewWithParentAndChild(int nestedScrollViewHeight, 615 int childHeight) throws Throwable { 616 final TestContentView testContentView = 617 mActivityTestRule.getActivity().findViewById(R.id.testContentView); 618 619 mNestedScrollView.setLayoutParams(new ViewGroup.LayoutParams( 620 ViewGroup.LayoutParams.MATCH_PARENT, nestedScrollViewHeight)); 621 mNestedScrollView.setMinimumHeight(nestedScrollViewHeight); 622 623 mChild.setLayoutParams(new ViewGroup.LayoutParams( 624 ViewGroup.LayoutParams.MATCH_PARENT, childHeight)); 625 mChild.setMinimumHeight(childHeight); 626 627 testContentView.expectLayouts(1); 628 mActivityTestRule.runOnUiThread(new Runnable() { 629 @Override 630 public void run() { 631 mNestedScrollView.addView(mChild); 632 mParent.addView(mNestedScrollView); 633 testContentView.addView(mParent); 634 } 635 }); 636 testContentView.awaitLayouts(2); 637 } 638 639 public class NestedScrollingSpyView extends FrameLayout implements NestedScrollingChild2, 640 NestedScrollingParent2 { 641 642 public NestedScrollingSpyView(Context context) { 643 super(context); 644 } 645 646 @Override 647 public boolean onStartNestedScroll(@NonNull View child, @NonNull View target, int axes, 648 int type) { 649 return false; 650 } 651 652 @Override 653 public void onNestedScrollAccepted(@NonNull View child, @NonNull View target, int axes, 654 int type) { 655 656 } 657 658 @Override 659 public void onStopNestedScroll(@NonNull View target, int type) { 660 661 } 662 663 @Override 664 public void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, 665 int dxUnconsumed, int dyUnconsumed, int type) { 666 667 } 668 669 @Override 670 public void onNestedPreScroll(@NonNull View target, int dx, int dy, @NonNull int[] consumed, 671 int type) { 672 673 } 674 675 @Override 676 public boolean startNestedScroll(int axes, int type) { 677 return false; 678 } 679 680 @Override 681 public void stopNestedScroll(int type) { 682 683 } 684 685 @Override 686 public boolean hasNestedScrollingParent(int type) { 687 return false; 688 } 689 690 @Override 691 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, 692 int dyUnconsumed, @Nullable int[] offsetInWindow, int type) { 693 return false; 694 } 695 696 @Override 697 public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed, 698 @Nullable int[] offsetInWindow, int type) { 699 return false; 700 } 701 702 @Override 703 public void setNestedScrollingEnabled(boolean enabled) { 704 705 } 706 707 @Override 708 public boolean isNestedScrollingEnabled() { 709 return false; 710 } 711 712 @Override 713 public boolean startNestedScroll(int axes) { 714 return false; 715 } 716 717 @Override 718 public void stopNestedScroll() { 719 720 } 721 722 @Override 723 public boolean hasNestedScrollingParent() { 724 return false; 725 } 726 727 @Override 728 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, 729 int dyUnconsumed, int[] offsetInWindow) { 730 return false; 731 } 732 733 @Override 734 public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, 735 int[] offsetInWindow) { 736 return false; 737 } 738 739 @Override 740 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 741 return false; 742 } 743 744 @Override 745 public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 746 return false; 747 } 748 749 @Override 750 public boolean onStartNestedScroll(View child, View target, int axes) { 751 return false; 752 } 753 754 @Override 755 public void onNestedScrollAccepted(View child, View target, int axes) { 756 757 } 758 759 @Override 760 public void onStopNestedScroll(View target) { 761 762 } 763 764 @Override 765 public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, 766 int dyUnconsumed) { 767 768 } 769 770 @Override 771 public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 772 773 } 774 775 @Override 776 public boolean onNestedFling(View target, float velocityX, float velocityY, 777 boolean consumed) { 778 return false; 779 } 780 781 @Override 782 public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 783 return false; 784 } 785 786 @Override 787 public int getNestedScrollAxes() { 788 return 0; 789 } 790 } 791 792} 793