From c418063205d74233a6235d7f7fd39be7deeb4bc7 Mon Sep 17 00:00:00 2001 From: hunterstich Date: Tue, 26 Sep 2023 15:03:04 -0400 Subject: [PATCH] [Carousel] Fixed strategies crashing when there is not enough available space for a large and a small item If the carousel container is not large enough to fit a small item and large item that is at least as large as the minimum small item size, mutli-browse and hero strategies will create an arrangment with a single, large item. PiperOrigin-RevId: 568610428 --- .../android/material/carousel/HeroCarouselStrategy.java | 9 +++++++-- .../material/carousel/MultiBrowseCarouselStrategy.java | 8 ++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/java/com/google/android/material/carousel/HeroCarouselStrategy.java b/lib/java/com/google/android/material/carousel/HeroCarouselStrategy.java index 86dddf88fd0..0e48773714e 100644 --- a/lib/java/com/google/android/material/carousel/HeroCarouselStrategy.java +++ b/lib/java/com/google/android/material/carousel/HeroCarouselStrategy.java @@ -82,6 +82,11 @@ KeylineState onFirstChildMeasuredWithMargins(@NonNull Carousel carousel, @NonNul getSmallSizeMax(child.getContext()) + childMargins); float targetMediumChildSize = (targetLargeChildSize + targetSmallChildSize) / 2F; + int[] smallCounts = SMALL_COUNTS; + if (availableSpace < smallChildSizeMin * 2) { + smallCounts = new int[] { 0 }; + } + // Find the minimum space left for large items after filling the carousel with the most // permissible small items to determine a plausible minimum large count. float minAvailableLargeSpace = availableSpace - (smallChildSizeMax * maxValue(SMALL_COUNTS)); @@ -100,8 +105,8 @@ KeylineState onFirstChildMeasuredWithMargins(@NonNull Carousel carousel, @NonNul smallChildSizeMin, smallChildSizeMax, isCenterAligned - ? doubleCounts(SMALL_COUNTS) - : SMALL_COUNTS, + ? doubleCounts(smallCounts) + : smallCounts, targetMediumChildSize, isCenterAligned ? doubleCounts(MEDIUM_COUNTS) diff --git a/lib/java/com/google/android/material/carousel/MultiBrowseCarouselStrategy.java b/lib/java/com/google/android/material/carousel/MultiBrowseCarouselStrategy.java index 4746f99fac6..96c23b015d9 100644 --- a/lib/java/com/google/android/material/carousel/MultiBrowseCarouselStrategy.java +++ b/lib/java/com/google/android/material/carousel/MultiBrowseCarouselStrategy.java @@ -118,11 +118,19 @@ KeylineState onFirstChildMeasuredWithMargins(@NonNull Carousel carousel, @NonNul // then finally 1. int[] smallCounts = SMALL_COUNTS; + if (availableSpace < smallChildSizeMin * 2) { + // If the available space is too small to fit a large item and small item and a large item + // (large items must be at least as big as a small item), allow arrangements with no small + // items. + smallCounts = new int[] { 0 }; + } + int[] mediumCounts = forceCompactArrangement ? MEDIUM_COUNTS_COMPACT : MEDIUM_COUNTS; if (carousel.getCarouselAlignment() == CarouselLayoutManager.ALIGNMENT_CENTER) { smallCounts = doubleCounts(smallCounts); mediumCounts = doubleCounts(mediumCounts); } + // Find the minimum space left for large items after filling the carousel with the most // permissible medium and small items to determine a plausible minimum large count. float minAvailableLargeSpace =