Composables UI is out: our new component library for Compose Multiplatform ->
Composable Function

rememberTransformingLazyColumnFirstLayoutItemProvider

Creates and remembers a TransformingLazyColumnFirstLayoutItemProvider that delegates to the provided itemInfo lambda.

TransformingLazyColumnFirstLayoutItemProviderSample

@Preview
@Composable
fun TransformingLazyColumnFirstLayoutItemProviderSample() {
    val state = rememberTransformingLazyColumnState()
    val transformationSpec = rememberTransformationSpec()
    // This sample demonstrates how to use rememberTransformingLazyColumnFirstLayoutItemProvider
    // to control the expansion direction of a dynamically resizing item. By using the voice input
    // card's Bottom/End edge as the layout reference, the card predictably expands upwards.
    // The constant key safely falls back to default layout behavior when scrolled off-screen.
    val firstLayoutItemProvider = rememberTransformingLazyColumnFirstLayoutItemProvider {
        state.layoutItemInfoOf(
            itemKey = "voice_input",
            itemEdge = TransformingLazyColumnFirstLayoutItemProvider.ItemEdge.End,
        )
    }
    var isListening by remember { mutableStateOf(false) }
    var lineCount by remember { mutableIntStateOf(0) }
    // Simple loop simulating text lines arriving over time
    LaunchedEffect(isListening) {
        if (isListening) {
            while (lineCount < 5) {
                delay(300)
                lineCount++
            }
            isListening = false
        }
    }
    AppScaffold {
        ScreenScaffold(state) { contentPadding ->
            TransformingLazyColumn(
                state = state,
                contentPadding = contentPadding,
                firstLayoutItemProvider = firstLayoutItemProvider,
            ) {
                items(count = 3, key = { "message_$it" }) { index ->
                    Card(
                        onClick = {},
                        modifier =
                            Modifier.minimumVerticalContentPadding(
                                    CardDefaults.minimumVerticalListContentPadding
                                )
                                .transformedHeight(this, transformationSpec)
                                .animateItem(placementSpec = null),
                        transformation = SurfaceTransformation(transformationSpec),
                    ) {
                        Text("Previous message $index")
                    }
                }
                item(key = "voice_input") {
                    val voiceText = (1..lineCount).joinToString("\n") { "Voice Input line $it" }
                    OutlinedCard(
                        onClick = {
                            if (lineCount >= 5) lineCount = 0
                            isListening = !isListening
                        },
                        modifier =
                            Modifier.minimumVerticalContentPadding(
                                    CardDefaults.minimumVerticalListContentPadding
                                )
                                .transformedHeight(this, transformationSpec)
                                .animateItem(placementSpec = null),
                        transformation = SurfaceTransformation(transformationSpec),
                    ) {
                        Text(text = voiceText.ifEmpty { "Tap to speak" })
                    }
                }
            }
        }
    }
}

Last updated: