@@ -104,7 +104,7 @@ public class CarouselLayoutManager extends LayoutManager
104104 /** Vertical orientation for Carousel. */
105105 public static final int VERTICAL = RecyclerView .VERTICAL ;
106106
107- @ RecyclerView . Orientation private int orientation ;
107+ private CarouselOrientationHelper orientationHelper ;
108108
109109 /**
110110 * An internal object used to store and run checks on a child to be potentially added to the
@@ -145,14 +145,14 @@ public CarouselLayoutManager(@NonNull CarouselStrategy strategy) {
145145 public CarouselLayoutManager (
146146 @ NonNull CarouselStrategy strategy , @ RecyclerView .Orientation int orientation ) {
147147 setCarouselStrategy (strategy );
148- this . orientation = orientation ;
148+ setOrientation ( orientation ) ;
149149 }
150150
151151 @ SuppressLint ("UnknownNullness" ) // b/240775049: Cannot annotate properly
152152 public CarouselLayoutManager (
153153 Context context , AttributeSet attrs , int defStyleAttr , int defStyleRes ) {
154154 Properties properties = getProperties (context , attrs , defStyleAttr , defStyleRes );
155- this . orientation = properties .orientation ;
155+ setOrientation ( properties .orientation ) ;
156156 setCarouselStrategy (new MultiBrowseCarouselStrategy ());
157157 }
158158
@@ -422,24 +422,9 @@ private ChildCalculations makeChildCalculations(Recycler recycler, float start,
422422 private void addAndLayoutView (View child , int index , ChildCalculations calculations ) {
423423 float halfItemSize = currentKeylineState .getItemSize () / 2F ;
424424 addView (child , index );
425- int left ;
426- int top ;
427- int bottom ;
428- int right ;
429425 int start = (int ) (calculations .offsetCenter - halfItemSize );
430426 int end = (int ) (calculations .offsetCenter + halfItemSize );
431- if (isHorizontal ()) {
432- left = start ;
433- top = getParentTop ();
434- right = end ;
435- bottom = getParentBottom ();
436- } else {
437- left = getParentLeft ();
438- top = start ;
439- right = getParentRight ();
440- bottom = end ;
441- }
442- layoutDecoratedWithMargins (child , left , top , right , bottom );
427+ orientationHelper .layoutDecoratedWithMargins (child , start , end );
443428 updateChildMaskForLocation (child , calculations .center , calculations .range );
444429 }
445430
@@ -463,7 +448,7 @@ private boolean isLocOffsetOutOfFillBoundsStart(float locOffset, KeylineRange ra
463448
464449 @ Override
465450 public boolean isHorizontal () {
466- return orientation == HORIZONTAL ;
451+ return orientationHelper . orientation == HORIZONTAL ;
467452 }
468453
469454 /**
@@ -765,9 +750,7 @@ private float calculateChildOffsetCenterForLocation(
765750 // has scrolled in the end-to-end layout. Then use that value calculate what would be a
766751 // Keyline#locOffset.
767752 LayoutParams lp = (LayoutParams ) child .getLayoutParams ();
768- float marginMask =
769- (isHorizontal () ? (lp .rightMargin + lp .leftMargin ) : (lp .topMargin + lp .bottomMargin ))
770- / currentKeylineState .getItemSize ();
753+ float marginMask = orientationHelper .getMaskMargins (lp ) / currentKeylineState .getItemSize ();
771754 float outOfBoundOffset =
772755 (childCenterLocation - range .rightOrBottom .loc )
773756 * (1F - range .rightOrBottom .mask + marginMask );
@@ -826,64 +809,28 @@ private void updateChildMaskForLocation(
826809 float maskWidth = lerp (0F , childWidth / 2F , 0F , 1F , maskProgress );
827810 float maskHeight = lerp (0F , childHeight / 2F , 0F , 1F , maskProgress );
828811
829- RectF maskRect = new RectF (0F , maskHeight , childWidth , childHeight - maskHeight );
830- if (isHorizontal ()) {
831- maskRect = new RectF (maskWidth , 0F , (childWidth - maskWidth ), childHeight );
832- }
812+ RectF maskRect = orientationHelper .getMaskRect (childHeight , childWidth , maskHeight , maskWidth );
833813
834814 float offsetCenter = calculateChildOffsetCenterForLocation (child , childCenterLocation , range );
835815 float maskedTop = offsetCenter - (maskRect .height () / 2F );
836816 float maskedBottom = offsetCenter + (maskRect .height () / 2F );
837817 float maskedLeft = offsetCenter - (maskRect .width () / 2F );
838818 float maskedRight = offsetCenter + (maskRect .width () / 2F );
839819
820+ RectF offsetMaskRect = new RectF (maskedLeft , maskedTop , maskedRight , maskedBottom );
821+ RectF parentBoundsRect =
822+ new RectF (getParentLeft (), getParentTop (), getParentRight (), getParentBottom ());
840823 // If the carousel is a CONTAINED carousel, ensure the mask collapses against the side of the
841824 // container instead of bleeding and being clipped by the RecyclerView's bounds.
842825 // Only do this if there is only one side of the mask that is out of bounds; if
843826 // both sides are out of bounds on the same side, then the whole mask is out of view.
844827 if (carouselStrategy .isContained ()) {
845- if (isHorizontal ()) {
846- if (maskedLeft < getParentLeft () && maskedRight > getParentLeft ()) {
847- float diff = getParentLeft () - maskedLeft ;
848- maskRect .left += diff ;
849- maskedLeft += diff ;
850- }
851- if (maskedRight > getParentRight () && maskedLeft < getParentRight ()) {
852- float diff = maskedRight - getParentRight ();
853- maskRect .right = max (maskRect .right - diff , maskRect .left );
854- maskedRight = max (maskedRight - diff , maskedLeft );
855- }
856- } else {
857- if (maskedTop < getParentTop () && maskedBottom > getParentTop ()) {
858- float diff = getParentTop () - maskedTop ;
859- maskRect .top += diff ;
860- maskedTop += diff ;
861- }
862- if (maskedBottom > getParentBottom () && maskedTop < getParentBottom ()) {
863- float diff = maskedBottom - getParentBottom ();
864- maskRect .bottom = max (maskRect .bottom - diff , maskRect .top );
865- maskedBottom = max (maskedBottom - diff , maskedTop );
866- }
867- }
828+ orientationHelper .containMaskWithinBounds (maskRect , offsetMaskRect , parentBoundsRect );
868829 }
869830
870831 // 'Push out' any masks that are on the parent edge by rounding up/down and adding or
871832 // subtracting a pixel. Otherwise, the mask on the 'edge' looks like it has a width of 1 pixel.
872- if (isHorizontal ()) {
873- if (maskedRight <= getParentLeft ()) {
874- maskRect .right = (float ) Math .floor (maskRect .right ) - 1 ;
875- }
876- if (maskedLeft >= getParentRight ()) {
877- maskRect .left = (float ) Math .ceil (maskRect .left ) + 1 ;
878- }
879- } else {
880- if (maskedBottom <= getParentTop ()) {
881- maskRect .bottom = (float ) Math .floor (maskRect .bottom ) - 1 ;
882- }
883- if (maskedTop >= getParentBottom ()) {
884- maskRect .top = (float ) Math .ceil (maskRect .top ) + 1 ;
885- }
886- }
833+ orientationHelper .moveMaskOnEdgeOutsideBounds (maskRect , offsetMaskRect , parentBoundsRect );
887834 ((Maskable ) child ).setMaskRectF (maskRect );
888835 }
889836
@@ -906,11 +853,11 @@ public void measureChildWithMargins(@NonNull View child, int widthUsed, int heig
906853 // Otherwise, measure the item to what it would like to be so the strategy will be given an
907854 // opportunity to use this desired size in making it's sizing decision.
908855 final float childWidthDimension =
909- keylineStateList != null && orientation == HORIZONTAL
856+ keylineStateList != null && orientationHelper . orientation == HORIZONTAL
910857 ? keylineStateList .getDefaultState ().getItemSize ()
911858 : lp .width ;
912859 final float childHeightDimension =
913- keylineStateList != null && orientation == VERTICAL
860+ keylineStateList != null && orientationHelper . orientation == VERTICAL
914861 ? keylineStateList .getDefaultState ().getItemSize ()
915862 : lp .height ;
916863 final int widthSpec =
@@ -932,41 +879,27 @@ public void measureChildWithMargins(@NonNull View child, int widthUsed, int heig
932879 }
933880
934881 private int getParentLeft () {
935- if (isHorizontal ()) {
936- return 0 ;
937- }
938- return getPaddingLeft ();
882+ return orientationHelper .getParentLeft ();
939883 }
940884
941885 private int getParentStart () {
942- if (isHorizontal ()) {
943- return isLayoutRtl () ? getParentRight () : getParentLeft ();
944- }
945- return getParentTop ();
886+ return orientationHelper .getParentStart ();
946887 }
947888
948889 private int getParentRight () {
949- int right = getWidth ();
950- // If orientation is vertical, we want to subtract padding from the right.
951- if (!isHorizontal ()) {
952- right -= getPaddingRight ();
953- }
954- return right ;
890+ return orientationHelper .getParentRight ();
955891 }
956892
957893 private int getParentEnd () {
958- if (isHorizontal ()) {
959- return isLayoutRtl () ? getParentLeft () : getParentRight ();
960- }
961- return getParentBottom ();
894+ return orientationHelper .getParentEnd ();
962895 }
963896
964897 private int getParentTop () {
965- return isHorizontal () ? getPaddingTop () : 0 ;
898+ return orientationHelper . getParentTop () ;
966899 }
967900
968901 private int getParentBottom () {
969- return isHorizontal () ? getHeight () - getPaddingBottom () : getHeight ();
902+ return orientationHelper . getParentBottom ();
970903 }
971904
972905 @ Override
@@ -990,7 +923,7 @@ private int getContainerSize() {
990923 return getContainerHeight ();
991924 }
992925
993- private boolean isLayoutRtl () {
926+ boolean isLayoutRtl () {
994927 return isHorizontal () && getLayoutDirection () == ViewCompat .LAYOUT_DIRECTION_RTL ;
995928 }
996929
@@ -1258,13 +1191,7 @@ private void offsetChild(View child, float startOffset, float halfItemSize, Rect
12581191 // Offset the child so its center is at offsetCenter
12591192 super .getDecoratedBoundsWithMargins (child , boundsRect );
12601193 updateChildMaskForLocation (child , center , range );
1261- if (isHorizontal ()) {
1262- float actualCx = boundsRect .left + halfItemSize ;
1263- child .offsetLeftAndRight ((int ) (offsetCenter - actualCx ));
1264- } else {
1265- float actualCy = boundsRect .top + halfItemSize ;
1266- child .offsetTopAndBottom ((int ) (offsetCenter - actualCy ));
1267- }
1194+ orientationHelper .offsetChild (child , boundsRect , halfItemSize , offsetCenter );
12681195 }
12691196
12701197 /**
@@ -1329,7 +1256,7 @@ public int computeVerticalScrollRange(@NonNull State state) {
13291256 */
13301257 @ RecyclerView .Orientation
13311258 public int getOrientation () {
1332- return orientation ;
1259+ return orientationHelper . orientation ;
13331260 }
13341261
13351262 /**
@@ -1344,8 +1271,8 @@ public void setOrientation(@RecyclerView.Orientation int orientation) {
13441271
13451272 assertNotInLayoutOrScroll (null );
13461273
1347- if (orientation != this .orientation ) {
1348- this . orientation = orientation ;
1274+ if (orientationHelper == null || orientation != orientationHelper .orientation ) {
1275+ orientationHelper = CarouselOrientationHelper . createOrientationHelper ( this , orientation ) ;
13491276 refreshKeylineState ();
13501277 }
13511278 }
0 commit comments