Karlo Vuljanko
07/20/2023, 10:18 AMIntrinsicSize.Max()
in lazy components. (Understandably)
is there an easy way to work around this or do i have to do some magic with SubcomposeLayout / Create quasi non lazy pager with Row composable?Stylianos Gakis
07/20/2023, 10:27 AMAnchoredDraggable
it seems.Karlo Vuljanko
07/20/2023, 10:40 AMKarlo Vuljanko
07/20/2023, 10:41 AMStylianos Gakis
07/20/2023, 10:43 AMKarlo Vuljanko
07/20/2023, 11:44 AMAlbert Chang
07/20/2023, 11:44 AMoffscreenLimit
to cover all the pages and you should be able to achieve what you want.Karlo Vuljanko
07/20/2023, 11:49 AMStylianos Gakis
07/20/2023, 11:49 AMColton Idle
07/21/2023, 10:34 PMColton Idle
07/21/2023, 10:34 PMStylianos Gakis
07/21/2023, 11:03 PMAndrey Kulikov
07/22/2023, 1:02 PMbeyondBoundsPageCount
param on HorizontalPager
from compose:foundation. but keep in mind that loading a lot of pages at once will affect your performance. sometimes a more reasonable approach is to react on size changes nicely, like with having animateContentSize modifier on Pager, or something like thisLukasz Kalnik
08/01/2025, 10:31 AMSubcomposeLayout
and the regular, lazy HorizontalPager
here, in case someone finds this thread:
fun OnboardingPager(onboardingCards: List<OnboardingCardState>) {
val pagerState = rememberPagerState(pageCount = { onboardingCards.size })
var maxCardHeight by remember { mutableStateOf(0.dp) }
val pagerContentPadding = 16.dp
// Measure the maximum height of all cards
SubcomposeLayout { constraints ->
val measuredHeights = onboardingCards.map { card ->
val placeables = subcompose(card) {
OnboardingCard(
onboardingCard = card,
modifier = Modifier.padding(horizontal = pagerContentPadding)
)
}.map { it.measure(constraints) }
placeables.maxOf { it.height.toDp() }
}
maxCardHeight = measuredHeights.maxOrNull() ?: 0.dp
layout(0, 0) {}
}
HorizontalPager(
state = pagerState,
pageSpacing = 16.dp,
verticalAlignment = Alignment.Top,
contentPadding = PaddingValues(horizontal = pagerContentPadding),
)
{ page ->
OnboardingCard(
onboardingCard = onboardingCards[page],
modifier = Modifier.height(maxCardHeight)
)
}
// ...
Lukasz Kalnik
08/01/2025, 10:35 AMSubcomposeLayout
just measures all the `OnboardingCard`s here, which are displayed in HorizontalPager
.
It is important to pass the same constraints to the `OnboardingCard`s inside the SubcomposeLayout
, that's why I pass the pagerContentPadding
both to the card in the SubcomposeLayout
and to the HorizontalPager
itself.
Otherwise the card will assume it has more horizontal space and will cut off the content of the highest pages in the HorizontalPager
.Lukasz Kalnik
08/01/2025, 10:36 AMSubcomposeLayout
is executed during layout phase, after measuring and before placing items.
It doesn't draw anything on the screen. It's sole purpose is if you need to measure some Composables (e.g. here the OnboardingCard
) to pass the result to some other Composable (here it is passed to the OnboardingCard
inside the HorizontalPager
in the Modifier.height(maxCardHeight)
).Andrey Kulikov
08/01/2025, 10:50 AMLukasz Kalnik
08/01/2025, 10:50 AMLukasz Kalnik
08/01/2025, 10:51 AMitemsCount
to beyondViewportPageCount
didn't fix the problemLukasz Kalnik
08/01/2025, 10:51 AMLukasz Kalnik
08/01/2025, 10:51 AMHorizontalPager
height doesn't changeLukasz Kalnik
08/01/2025, 10:52 AMLukasz Kalnik
08/01/2025, 10:53 AMModifier.height(Intrinsics.Max)
to the pages, because they all will be composed eagerly then?Lukasz Kalnik
08/01/2025, 10:56 AMHorizontalPager(
// ...
beyondViewportPageCount = itemsCount
// ...
) { page ->
Page(Modifier.height(IntrinsicsSize.Max))
}
Andrey Kulikov
08/01/2025, 10:57 AMLukasz Kalnik
08/01/2025, 10:58 AM