Skip to content

Commit 966f7da

Browse files
committed
[Carousel] Fix orientation not correct in item decoration calculations
Resolves #3500 PiperOrigin-RevId: 558825973
1 parent dc91b39 commit 966f7da

File tree

1 file changed

+59
-50
lines changed

1 file changed

+59
-50
lines changed

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

Lines changed: 59 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,10 @@ private void logChildrenIfDebugging() {
419419
Log.d(TAG, "internal representation of views on the screen");
420420
for (int i = 0; i < getChildCount(); i++) {
421421
View child = getChildAt(i);
422-
float centerX = getDecoratedCenterXWithMargins(child);
422+
float center = getDecoratedCenterWithMargins(child);
423423
Log.d(
424424
TAG,
425-
"item position " + getPosition(child) + ", center:" + centerX + ", child index:" + i);
425+
"item position " + getPosition(child) + ", center:" + center + ", child index:" + i);
426426
}
427427
Log.d(TAG, "==============");
428428
}
@@ -560,22 +560,30 @@ private boolean isLocOffsetOutOfFillBoundsEnd(float locOffset, KeylineRange rang
560560
@Override
561561
public void getDecoratedBoundsWithMargins(@NonNull View view, @NonNull Rect outBounds) {
562562
super.getDecoratedBoundsWithMargins(view, outBounds);
563-
float centerX = outBounds.centerX();
563+
float center = outBounds.centerY();
564+
if (isHorizontal()) {
565+
center = outBounds.centerX();
566+
}
564567
float maskedSize =
565568
getMaskedItemSizeForLocOffset(
566-
centerX, getSurroundingKeylineRange(currentKeylineState.getKeylines(), centerX, true));
567-
float delta = (outBounds.width() - maskedSize) / 2F;
569+
center, getSurroundingKeylineRange(currentKeylineState.getKeylines(), center, true));
570+
float deltaX = isHorizontal() ? (outBounds.width() - maskedSize) / 2F : 0;
571+
float deltaY = isHorizontal() ? 0 : (outBounds.height() - maskedSize) / 2F;
572+
568573
outBounds.set(
569-
(int) (outBounds.left + delta),
570-
outBounds.top,
571-
(int) (outBounds.right - delta),
572-
outBounds.bottom);
574+
(int) (outBounds.left + deltaX),
575+
(int) (outBounds.top + deltaY),
576+
(int) (outBounds.right - deltaX),
577+
(int) (outBounds.bottom - deltaY));
573578
}
574579

575-
private float getDecoratedCenterXWithMargins(View child) {
580+
private float getDecoratedCenterWithMargins(View child) {
576581
Rect bounds = new Rect();
577582
super.getDecoratedBoundsWithMargins(child, bounds);
578-
return bounds.centerX();
583+
if (isHorizontal()) {
584+
return bounds.centerX();
585+
}
586+
return bounds.centerY();
579587
}
580588

581589
/**
@@ -591,10 +599,10 @@ private void removeAndRecycleOutOfBoundsViews(Recycler recycler) {
591599
// Remove items that are out of bounds at the head of the list
592600
while (getChildCount() > 0) {
593601
View child = getChildAt(0);
594-
float centerX = getDecoratedCenterXWithMargins(child);
602+
float center = getDecoratedCenterWithMargins(child);
595603
KeylineRange range =
596-
getSurroundingKeylineRange(currentKeylineState.getKeylines(), centerX, true);
597-
if (isLocOffsetOutOfFillBoundsStart(centerX, range)) {
604+
getSurroundingKeylineRange(currentKeylineState.getKeylines(), center, true);
605+
if (isLocOffsetOutOfFillBoundsStart(center, range)) {
598606
removeAndRecycleView(child, recycler);
599607
} else {
600608
break;
@@ -604,10 +612,10 @@ private void removeAndRecycleOutOfBoundsViews(Recycler recycler) {
604612
// Remove items that are out of bounds at the tail of the list
605613
while (getChildCount() - 1 >= 0) {
606614
View child = getChildAt(getChildCount() - 1);
607-
float centerX = getDecoratedCenterXWithMargins(child);
615+
float center = getDecoratedCenterWithMargins(child);
608616
KeylineRange range =
609-
getSurroundingKeylineRange(currentKeylineState.getKeylines(), centerX, true);
610-
if (isLocOffsetOutOfFillBoundsEnd(centerX, range)) {
617+
getSurroundingKeylineRange(currentKeylineState.getKeylines(), center, true);
618+
if (isLocOffsetOutOfFillBoundsEnd(center, range)) {
611619
removeAndRecycleView(child, recycler);
612620
} else {
613621
break;
@@ -625,71 +633,72 @@ private void removeAndRecycleOutOfBoundsViews(Recycler recycler) {
625633
* together.
626634
*
627635
* <p>If no keyline is found for the left, the left-most keyline is returned. If no keyline to the
628-
* right is found, the right-most keyline is returned. This means the {@code location} is outside
629-
* the bounds of the outer-most keylines.
636+
* right is found, the right-most keyline is returned. If the orientation is vertical, the same
637+
* goes for top-most and bottom-most keylines respectively. This means the {@code location} is
638+
* outside the bounds of the outer-most keylines.
630639
*
631640
* @param location The location along the scrolling axis that should be contained by the returned
632641
* keyline range. This can be either a location in the end-to-end model ({@link Keyline#loc}
633642
* or in the offset model {@link Keyline#locOffset}.
634643
* @param isOffset true if {@code location} has been offset and should be compared against {@link
635644
* Keyline#locOffset}, false if {@code location} should be compared against {@link
636645
* Keyline#loc}.
637-
* @return A pair whose first item is the nearest {@link Keyline} before centerX and whose second
638-
* item is the nearest {@link Keyline} after centerX.
646+
* @return A pair whose first item is the nearest {@link Keyline} before center and whose second
647+
* item is the nearest {@link Keyline} after center.
639648
*/
640649
private static KeylineRange getSurroundingKeylineRange(
641650
List<Keyline> keylines, float location, boolean isOffset) {
642-
int leftMinDistanceIndex = -1;
643-
float leftMinDistance = Float.MAX_VALUE;
644-
int leftMostIndex = -1;
645-
float leftMostX = Float.MAX_VALUE;
651+
int startMinDistanceIndex = -1;
652+
float startMinDistance = Float.MAX_VALUE;
653+
int startMostIndex = -1;
654+
float startMostX = Float.MAX_VALUE;
646655

647-
int rightMinDistanceIndex = -1;
648-
float rightMinDistance = Float.MAX_VALUE;
649-
int rightMostIndex = -1;
650-
float rightMostX = -Float.MAX_VALUE;
656+
int endMinDistanceIndex = -1;
657+
float endMinDistance = Float.MAX_VALUE;
658+
int endMostIndex = -1;
659+
float endMostX = -Float.MAX_VALUE;
651660

652661
for (int i = 0; i < keylines.size(); i++) {
653662
Keyline keyline = keylines.get(i);
654663
float currentLoc = isOffset ? keyline.locOffset : keyline.loc;
655664
float delta = abs(currentLoc - location);
656665

657-
// Find the keyline closest to the left of centerX with the lowest index.
666+
// Find the keyline closest to the left of center with the lowest index.
658667
if (currentLoc <= location) {
659-
if (delta <= leftMinDistance) {
660-
leftMinDistance = delta;
661-
leftMinDistanceIndex = i;
668+
if (delta <= startMinDistance) {
669+
startMinDistance = delta;
670+
startMinDistanceIndex = i;
662671
}
663672
}
664-
// The keyline is to the right of centerX
665-
// Find the keyline closest to the right of centerX with the greatest index.
666-
if (currentLoc > location && delta <= rightMinDistance) {
667-
rightMinDistance = delta;
668-
rightMinDistanceIndex = i;
673+
// The keyline is to the right of center
674+
// Find the keyline closest to the right of center with the greatest index.
675+
if (currentLoc > location && delta <= endMinDistance) {
676+
endMinDistance = delta;
677+
endMinDistanceIndex = i;
669678
}
670679
// Find the left-most keyline
671-
if (currentLoc <= leftMostX) {
672-
leftMostIndex = i;
673-
leftMostX = currentLoc;
680+
if (currentLoc <= startMostX) {
681+
startMostIndex = i;
682+
startMostX = currentLoc;
674683
}
675684
// Find the right-most keyline
676-
if (currentLoc > rightMostX) {
677-
rightMostIndex = i;
678-
rightMostX = currentLoc;
685+
if (currentLoc > endMostX) {
686+
endMostIndex = i;
687+
endMostX = currentLoc;
679688
}
680689
}
681690

682-
// If a keyline to the left or right hasn't been found, centerX is outside the bounds of the
691+
// If a keyline to the left or right hasn't been found, center is outside the bounds of the
683692
// outer-most keylines. Use the outer-most keyline instead.
684-
if (leftMinDistanceIndex == -1) {
685-
leftMinDistanceIndex = leftMostIndex;
693+
if (startMinDistanceIndex == -1) {
694+
startMinDistanceIndex = startMostIndex;
686695
}
687-
if (rightMinDistanceIndex == -1) {
688-
rightMinDistanceIndex = rightMostIndex;
696+
if (endMinDistanceIndex == -1) {
697+
endMinDistanceIndex = endMostIndex;
689698
}
690699

691700
return new KeylineRange(
692-
keylines.get(leftMinDistanceIndex), keylines.get(rightMinDistanceIndex));
701+
keylines.get(startMinDistanceIndex), keylines.get(endMinDistanceIndex));
693702
}
694703

695704
/**

0 commit comments

Comments
 (0)