@@ -140,6 +140,17 @@ Keyline getLastNonAnchorKeyline() {
140140 return null ;
141141 }
142142
143+ /** Returns how many non-anchor keylines. */
144+ int getNumberOfNonAnchorKeylines () {
145+ int anchorKeylines = 0 ;
146+ for (Keyline keyline : keylines ) {
147+ if (keyline .isAnchor ) {
148+ anchorKeylines += 1 ;
149+ }
150+ }
151+ return keylines .size () - anchorKeylines ;
152+ }
153+
143154 /**
144155 * Linearly interpolate between two {@link KeylineState}s.
145156 *
@@ -337,7 +348,9 @@ Builder addKeyline(
337348 float maskedItemSize ,
338349 boolean isFocal ,
339350 boolean isAnchor ,
340- float cutoff ) {
351+ float cutoff ,
352+ float leftOrTopPaddingShift ,
353+ float rightOrBottomPaddingShift ) {
341354 if (maskedItemSize <= 0F ) {
342355 return this ;
343356 }
@@ -353,7 +366,8 @@ Builder addKeyline(
353366 }
354367
355368 Keyline tmpKeyline =
356- new Keyline (UNKNOWN_LOC , offsetLoc , mask , maskedItemSize , isAnchor , cutoff );
369+ new Keyline (UNKNOWN_LOC , offsetLoc , mask , maskedItemSize , isAnchor , cutoff ,
370+ leftOrTopPaddingShift , rightOrBottomPaddingShift );
357371 if (isFocal ) {
358372 if (tmpFirstFocalKeyline == null ) {
359373 tmpFirstFocalKeyline = tmpKeyline ;
@@ -388,6 +402,44 @@ Builder addKeyline(
388402 return this ;
389403 }
390404
405+ /**
406+ * Adds a keyline along the scrolling axis where an object should be masked by the given {@code
407+ * mask} and positioned at {@code offsetLoc}.
408+ *
409+ * <p>Note that calls to {@link #addKeyline(float, float, float, boolean, boolean)} and {@link
410+ * #addKeylineRange(float, float, float, int)} are added in order. Typically, this means
411+ * keylines should be added in order of ascending {@code offsetLoc}. The first and last keylines
412+ * added are 'anchor' keylines that mark the start and ends of the keylines. These keylines do
413+ * not shift when scrolled.
414+ *
415+ * <p>Note also that {@code isFocal} and {@code isAnchor} cannot be true at the same time as
416+ * anchor keylines refer to keylines offscreen that dictate the ends of the keylines.
417+ *
418+ * @param offsetLoc The location of this keyline along the scrolling axis. An offsetLoc of 0
419+ * will be at the start of the scroll container.
420+ * @param mask The percentage of a child's full size that it should be masked by when its center
421+ * is at {@code offsetLoc}. 0 is fully unmasked and 1 is fully masked.
422+ * @param maskedItemSize The total size of this item when masked. This might differ from {@code
423+ * itemSize - (itemSize * mask)} depending on how margins are included in the {@code mask}.
424+ * @param isFocal Whether this keyline is considered part of the focal range. Typically, this is
425+ * when {@code mask} is equal to 0.
426+ * @param isAnchor Whether this keyline is an anchor keyline. Anchor keylines do not shift when
427+ * keylines are shifted.
428+ * @param cutoff How much the keyline item is out the bounds of the available space.
429+ */
430+ @ NonNull
431+ @ CanIgnoreReturnValue
432+ Builder addKeyline (
433+ float offsetLoc ,
434+ @ FloatRange (from = 0.0F , to = 1.0F ) float mask ,
435+ float maskedItemSize ,
436+ boolean isFocal ,
437+ boolean isAnchor ,
438+ float cutoff ) {
439+ return addKeyline (offsetLoc , mask , maskedItemSize , isFocal , isAnchor , cutoff ,
440+ 0 , 0 );
441+ }
442+
391443 /**
392444 * Adds a keyline along the scrolling axis where an object should be masked by the given {@code
393445 * mask} and positioned at {@code offsetLoc}. This method also calculates the amount that a
@@ -537,7 +589,9 @@ KeylineState build() {
537589 tmpKeyline .mask ,
538590 tmpKeyline .maskedItemSize ,
539591 tmpKeyline .isAnchor ,
540- tmpKeyline .cutoff );
592+ tmpKeyline .cutoff ,
593+ tmpKeyline .leftOrTopPaddingShift ,
594+ tmpKeyline .rightOrBottomPaddingShift );
541595 keylines .add (keyline );
542596 }
543597
@@ -574,6 +628,8 @@ static final class Keyline {
574628 final float maskedItemSize ;
575629 final boolean isAnchor ;
576630 final float cutoff ;
631+ final float leftOrTopPaddingShift ;
632+ final float rightOrBottomPaddingShift ;
577633
578634 /**
579635 * Creates a non-anchor keyline along a scroll axis.
@@ -587,7 +643,8 @@ static final class Keyline {
587643 * @param maskedItemSize The size of this item when masked.
588644 */
589645 Keyline (float loc , float locOffset , float mask , float maskedItemSize ) {
590- this (loc , locOffset , mask , maskedItemSize , /* isAnchor= */ false , 0 );
646+ this (loc , locOffset , mask , maskedItemSize , /* isAnchor= */ false , 0 ,
647+ 0 , 0 );
591648 }
592649
593650 /**
@@ -603,20 +660,28 @@ static final class Keyline {
603660 * @param isAnchor Whether or not the keyline is an anchor keyline (keylines at the end that do
604661 * not shift).
605662 * @param cutoff The amount by which the keyline item is cut off by the bounds of the carousel.
663+ * @param leftOrTopPaddingShift The amount by which this keyline was shifted to account for left
664+ * or top padding
665+ * @param rightOrBottomPaddingShift The amount by which this keyline was shifted to account for
666+ * right or bottom padding
606667 */
607668 Keyline (
608669 float loc ,
609670 float locOffset ,
610671 float mask ,
611672 float maskedItemSize ,
612673 boolean isAnchor ,
613- float cutoff ) {
674+ float cutoff ,
675+ float leftOrTopPaddingShift ,
676+ float rightOrBottomPaddingShift ) {
614677 this .loc = loc ;
615678 this .locOffset = locOffset ;
616679 this .mask = mask ;
617680 this .maskedItemSize = maskedItemSize ;
618681 this .isAnchor = isAnchor ;
619682 this .cutoff = cutoff ;
683+ this .leftOrTopPaddingShift = leftOrTopPaddingShift ;
684+ this .rightOrBottomPaddingShift = rightOrBottomPaddingShift ;
620685 }
621686
622687 /** Linearly interpolates between two keylines and returns the interpolated object. */
0 commit comments