Skip to content

Commit 7822ef8

Browse files
imhappiraajkumars
authored andcommitted
[Carousel] Add orientation helper to clean up CarouselLayoutManager orientation differences
PiperOrigin-RevId: 543813088
1 parent d287c80 commit 7822ef8

File tree

2 files changed

+351
-98
lines changed

2 files changed

+351
-98
lines changed

lib/java/com/google/android/material/carousel/CarouselLayoutManager.java

Lines changed: 25 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)