@@ -309,6 +309,68 @@ public void testUncontainedLayout_allowsLastItemToBleed() throws Throwable {
309309 assertThat (lastItemMask .right ).isGreaterThan (DEFAULT_RECYCLER_VIEW_WIDTH );
310310 }
311311
312+ @ Test
313+ public void testMasksLeftOfParent_areRoundedDown () throws Throwable {
314+ layoutManager .setCarouselStrategy (
315+ new TestContainmentCarouselStrategy (/* isContained= */ false ));
316+ setAdapterItems (recyclerView , layoutManager , adapter , createDataSetWithSize (10 ));
317+ scrollHorizontallyBy (recyclerView , layoutManager , 900 );
318+
319+ for (int i = 0 ; i < recyclerView .getChildCount (); i ++) {
320+ View child = recyclerView .getChildAt (i );
321+ Rect itemMask = getMaskRectOffsetToRecyclerViewCoords ((MaskableFrameLayout ) child );
322+ assertThat (itemMask .right ).isNotEqualTo (0 );
323+ }
324+ }
325+
326+ @ Test
327+ public void testMaskOnLeftParentEdge_areRoundedUp () throws Throwable {
328+ layoutManager .setCarouselStrategy (
329+ new TestContainmentCarouselStrategy (/* isContained= */ false ));
330+ setAdapterItems (recyclerView , layoutManager , adapter , createDataSetWithSize (10 ));
331+ // Scroll to end
332+ scrollToPosition (recyclerView , layoutManager , 9 );
333+
334+ // Carousel strategy at end is {small, large}. Last child will be large item, second last
335+ // child will be small item. So third last child's right mask edge should not show.
336+ Rect thirdLastChildMask =
337+ getMaskRectOffsetToRecyclerViewCoords (
338+ (MaskableFrameLayout ) recyclerView .getChildAt (recyclerView .getChildCount () - 3 ));
339+ assertThat (thirdLastChildMask .right ).isLessThan (0 );
340+ assertThat (thirdLastChildMask .right ).isAtLeast (thirdLastChildMask .left );
341+ }
342+
343+ @ Test
344+ public void testMaskOnRightBoundary_areRoundedUp () throws Throwable {
345+ layoutManager .setCarouselStrategy (
346+ new TestContainmentCarouselStrategy (/* isContained= */ false ));
347+ setAdapterItems (recyclerView , layoutManager , adapter , createDataSetWithSize (10 ));
348+ scrollHorizontallyBy (recyclerView , layoutManager , 900 );
349+
350+ // For every child, assert that the mask left edge is located beyond the recycler view
351+ // width (parent's right edge).
352+ for (int i = recyclerView .getChildCount () - 1 ; i >= 0 ; i --) {
353+ View child = recyclerView .getChildAt (i );
354+ Rect itemMask = getMaskRectOffsetToRecyclerViewCoords ((MaskableFrameLayout ) child );
355+ assertThat (itemMask .left ).isNotEqualTo (DEFAULT_RECYCLER_VIEW_WIDTH );
356+ }
357+ }
358+
359+ @ Test
360+ public void testMaskOnRightParentEdge_areRoundedUp () throws Throwable {
361+ layoutManager .setCarouselStrategy (
362+ new TestContainmentCarouselStrategy (/* isContained= */ false ));
363+ setAdapterItems (recyclerView , layoutManager , adapter , createDataSetWithSize (10 ));
364+
365+ // Carousel strategy is {large, small}. First child will be large item, second child will
366+ // be small item, so the third child's left mask edge should not show up at the right parent
367+ // edge.
368+ Rect thirdChildMask =
369+ getMaskRectOffsetToRecyclerViewCoords ((MaskableFrameLayout ) recyclerView .getChildAt (2 ));
370+ assertThat (thirdChildMask .left ).isGreaterThan (DEFAULT_RECYCLER_VIEW_WIDTH );
371+ assertThat (thirdChildMask .left ).isAtMost (thirdChildMask .right );
372+ }
373+
312374 /**
313375 * Assigns explicit sizes to fixtures being used to construct the testing environment.
314376 *
0 commit comments