hey I have a very specific use case for a `LazyRow...
# compose
a
hey I have a very specific use case for a
LazyRow
- we want all our items to have the same visible height on screen. (i.e. the smallest visible item grow to fit the other tallest visible item). We cannot have a
Row
as that requires measuring all items including offscreen items, and we may have more than 5-10 ui elements. We also dont want to measure offscreen items until they reach visible, then reset the height modifiers on only visible ones if the height is
>
the previous value We currently use an
onGloballyPositioned
modifier like so:
Copy code
onGloballyPositioned {
                    if (props.rowHeight is RowHeight.MaxHeight) {
                        minHeightOnMaxHeightChange(with(density) { it.size.height.toDp() })
                    }
                }
we buffer the emission of each item so it only updates in smaller intervals if many are drawn on screen at once. It works in most cases and seems to be as performant as it can be. we then use a
CompositionLocal
to send the value to each item:
Copy code
val minHeightOnMaxHeight = LocalMaxHeightValue.current
carouselIntervalContent.item.invoke(
    this,
    info.index,
    Modifier.thenIf(props.rowHeight is RowHeight.MaxHeight) {
        minHeightOnMaxHeight.takeIf { it > 0.0.dp }?.let {
            heightIn(min = it)
        } ?: rowHeightModifier
    }
)
However, we discover that some kinds of content (depending on their internals) continuously grow until they reach a too large height and crash. Is there a better way to do this?
i discovered its due to a constraint in the child which may be a result of infinite height:
Copy code
Column(
            modifier = modifier
                .navigate(data),
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {
            Box(
                modifier = Modifier.fillMaxWidth(),
                contentAlignment = Alignment.Center
            ) {
                CommonImage(
                    data = data.image,
                    modifier = modifier
                        .padding(
                            start = Theme.blocks.edgeSpacing.dp,
                            end = Theme.blocks.edgeSpacing.dp,
                        )
                        .fillMaxWidth()
                )
            }
by switching it to having the aspect ratio set on the container for the image, it stopped happening:
Copy code
Column(
            modifier = modifier
                .navigate(data),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Box(
                modifier = Modifier.aspectRatio(1.0f),
                contentAlignment = Alignment.Center
            ) {
                CommonImage(
                    data = data.image,
                    modifier = modifier
                        .padding(
                            start = Theme.blocks.edgeSpacing.dp,
                            end = Theme.blocks.edgeSpacing.dp
                        )
                        .matchParentSize()
                )
            }
This is the solution I came up with a while back that we are still using on our project https://stackoverflow.com/a/73112412/3268303
1252 Views