androidx.wear.compose.material3.lazy

Interfaces

ResponsiveTransformationSpec

Version of TransformationSpec that supports variable screen sizes.

TransformationSpec

Defines visual transformations on the items of a TransformingLazyColumn.

TransformedPainterScope

Provides additional information to the painter inside TransformationSpec.

Classes

TransformationVariableSpec

This class represents the configuration parameters for one variable that changes as the item moves on the screen and will be used to apply the corresponding transformation - for example: container alpha.

Objects

Top-level functions summary

TransformationVariableSpec
lerp(
    start: TransformationVariableSpec,
    stop: TransformationVariableSpec,
    progress: Float
)

Helper function to lerp between the variables for different screen sizes.

ResponsiveTransformationSpec

Computes and remembers the appropriate TransformationSpec for the current screen size, given one or more TransformationSpecs for different screen sizes.

Extension functions summary

Modifier

A modifier that enables Material3 Motion transformations for content within a TransformingLazyColumn item.

Modifier
@Composable
Modifier.scrollTransform(
    scope: TransformingLazyColumnItemScope,
    backgroundColor: Color,
    shape: Shape
)

A modifier that enables Material3 Motion transformations for content within a TransformingLazyColumn item.

Modifier
@Composable
Modifier.scrollTransform(
    scope: TransformingLazyColumnItemScope,
    shape: Shape,
    painter: Painter,
    border: BorderStroke?
)

A modifier that enables Material3 Motion transformations for content within a TransformingLazyColumn item.

Modifier

This modifier provides the height of the target composable to the scrollTransform during a morph transition and represents minimum height of the item when morphed.

Top-level functions

fun lerp(
    start: TransformationVariableSpec,
    stop: TransformationVariableSpec,
    progress: Float
): TransformationVariableSpec

Helper function to lerp between the variables for different screen sizes.

rememberResponsiveTransformationSpec

@Composable
fun rememberResponsiveTransformationSpec(
    vararg specs: ResponsiveTransformationSpec
): ResponsiveTransformationSpec

Computes and remembers the appropriate TransformationSpec for the current screen size, given one or more TransformationSpecs for different screen sizes.

This shows use of the ResponsiveTransformationSpec which is a recommended TransformationSpec for large-screen aware Wear apps:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.ResponsiveTransformationSpecDefaults
import androidx.wear.compose.material3.lazy.TransformationSpec
import androidx.wear.compose.material3.lazy.TransformationVariableSpec
import androidx.wear.compose.material3.lazy.rememberResponsiveTransformationSpec

val transformationSpec =
    rememberResponsiveTransformationSpec(
        ResponsiveTransformationSpecDefaults.smallScreenSpec(
            // Makes the content disappear on the edges.
            contentAlpha = TransformationVariableSpec(0f)
        ),
        ResponsiveTransformationSpecDefaults.largeScreenSpec(
            // Makes the content disappear on the edges, but a bit more aggressively.
            contentAlpha =
                TransformationVariableSpec(0f, transformationZoneEnterFraction = 0.2f)
        ),
    )
TransformingLazyColumn(
    contentPadding = PaddingValues(20.dp),
    modifier = Modifier.background(Color.Black)
) {
    items(count = 100) { index ->
        TransformExclusion {
            Button(
                onClick = {},
                modifier =
                    Modifier.fillMaxWidth()
                        .transformedHeight(transformationSpec::getTransformedHeight)
                        .graphicsLayer {
                            with(transformationSpec) {
                                applyContainerTransformation(scrollProgress)
                            }
                        },
            ) {
                Text(
                    "Item $index",
                    modifier =
                        Modifier.graphicsLayer {
                            with(transformationSpec) {
                                applyContentTransformation(scrollProgress)
                            }
                        }
                )
            }
        }
    }
}

Extension functions

@Composable
fun Modifier.scrollTransform(scope: TransformingLazyColumnItemScope): Modifier

A modifier that enables Material3 Motion transformations for content within a TransformingLazyColumn item.

This modifier calculates and applies transformations to the content and background based on the TransformingLazyColumnItemScrollProgress of the item inside the TransformingLazyColumnItemScope. It adjusts the height, position, applies scaling and morphing effects as the item scrolls.

Note that in most cases is recommended to use one of the other overrides to explicitly provide Shape and background Color (or Painter) so the modifier can do the background drawing and apply specific effects to background and content, as in the Material spec.

When ReduceMotion is enabled, this modifier will not apply any transformations.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.LocalReduceMotion
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.EdgeButtonSize
import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.scrollTransform

var enableReduceMotion by remember { mutableStateOf(true) }
val state = rememberTransformingLazyColumnState()
AppScaffold {
    ScreenScaffold(
        state,
        contentPadding = PaddingValues(horizontal = 10.dp, vertical = 20.dp),
        modifier = Modifier.background(MaterialTheme.colorScheme.background),
        edgeButton = {
            EdgeButton(
                onClick = { enableReduceMotion = !enableReduceMotion },
                buttonSize = EdgeButtonSize.Large
            ) {
                Text("Toggle reduce motion")
            }
        }
    ) { contentPadding ->
        CompositionLocalProvider(LocalReduceMotion provides enableReduceMotion) {
            TransformingLazyColumn(
                state = state,
                contentPadding = contentPadding,
            ) {
                items(count = 5) {
                    Text(
                        "Text item $it",
                        modifier = Modifier.scrollTransform(this).animateItem()
                    )
                }
                items(count = 5) {
                    Button(onClick = {}, modifier = Modifier.fillMaxWidth().animateItem()) {
                        Text("Item $it")
                    }
                }
            }
        }
    }
}
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.scrollTransform

val state = rememberTransformingLazyColumnState()
val coroutineScope = rememberCoroutineScope()
var expandedItemKey by remember { mutableStateOf(-1) }
var elements by remember { mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) }

var nextElement = 10
fun addElement(index: Int) {
    elements =
        elements.subList(0, index) +
            listOf(nextElement++) +
            elements.subList(index, elements.count())
}

fun rainbowColor(progress: Float): Color {
    val hue = progress * 360f
    val saturation = 1f
    val value = 1f

    return Color(android.graphics.Color.HSVToColor(floatArrayOf(hue, saturation, value)))
}

AppScaffold {
    ScreenScaffold(
        state,
        edgeButton = {
            EdgeButton(
                onClick = {
                    addElement(elements.count())
                    coroutineScope.launch { state.scrollToItem(elements.count() - 1) }
                }
            ) {
                Text("Add item")
            }
        }
    ) { contentPadding ->
        val random = remember { Random }
        TransformingLazyColumn(
            state = state,
            contentPadding = contentPadding,
            modifier = Modifier.background(MaterialTheme.colorScheme.background)
        ) {
            items(elements, key = { it }) {
                val index = elements.indexOf(it)
                Column(
                    modifier =
                        Modifier.fillMaxWidth()
                            .scrollTransform(
                                this,
                                backgroundColor = MaterialTheme.colorScheme.surfaceContainer,
                                shape = MaterialTheme.shapes.medium
                            )
                            .animateItem()
                            .padding(5.dp)
                            .clickable {
                                elements =
                                    elements.subList(0, index) +
                                        elements.subList(index + 1, elements.count())
                            }
                ) {
                    Row(
                        verticalAlignment = CenterVertically,
                        horizontalArrangement = spacedBy(2.dp)
                    ) {
                        Text(
                            "Item $it",
                            color = MaterialTheme.colorScheme.onSurface,
                            style = MaterialTheme.typography.bodyLarge,
                            modifier = Modifier.weight(1f).fillMaxHeight()
                        )
                        Text("^", Modifier.clickable { addElement(index) })
                        Box(
                            Modifier.size(25.dp)
                                .drawWithContent {
                                    with(scrollProgress) {
                                        if (isUnspecified) {
                                            return@with
                                        }
                                        drawContent()
                                        val colorProgress =
                                            (topOffsetFraction + bottomOffsetFraction) / 2f
                                        val r = size.height / 2f
                                        drawCircle(
                                            rainbowColor(colorProgress),
                                            radius = r,
                                            center = Offset(size.width - r, r)
                                        )
                                        drawCircle(
                                            rainbowColor(random.nextFloat()),
                                            radius = r / 8,
                                            center = Offset(size.width - r, r)
                                        )
                                    }
                                }
                                .clickable {
                                    expandedItemKey =
                                        if (expandedItemKey == it) -1
                                        else {
                                            coroutineScope.launch { state.scrollToItem(index) }
                                            it
                                        }
                                }
                        )
                    }
                    AnimatedVisibility(expandedItemKey == it) {
                        // Expanded content goes here.
                        Box(modifier = Modifier.fillMaxWidth().height(100.dp))
                    }
                }
            }
        }
    }
}
Parameters
scope: TransformingLazyColumnItemScope

The TransformingLazyColumnItemScope provides access to the item's index and key.

@Composable
fun Modifier.scrollTransform(
    scope: TransformingLazyColumnItemScope,
    backgroundColor: Color,
    shape: Shape = RectangleShape
): Modifier

A modifier that enables Material3 Motion transformations for content within a TransformingLazyColumn item. It also draws the background behind the content using Material3 Motion transformations.

This modifier calculates and applies transformations to the content based on the TransformingLazyColumnItemScrollProgress of the item inside the TransformingLazyColumn. It adjusts the height, position, applies scaling and morphing effects as the item scrolls.

When ReduceMotion is enabled, this modifier will not apply any transformations.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.LocalReduceMotion
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.EdgeButtonSize
import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.scrollTransform

var enableReduceMotion by remember { mutableStateOf(true) }
val state = rememberTransformingLazyColumnState()
AppScaffold {
    ScreenScaffold(
        state,
        contentPadding = PaddingValues(horizontal = 10.dp, vertical = 20.dp),
        modifier = Modifier.background(MaterialTheme.colorScheme.background),
        edgeButton = {
            EdgeButton(
                onClick = { enableReduceMotion = !enableReduceMotion },
                buttonSize = EdgeButtonSize.Large
            ) {
                Text("Toggle reduce motion")
            }
        }
    ) { contentPadding ->
        CompositionLocalProvider(LocalReduceMotion provides enableReduceMotion) {
            TransformingLazyColumn(
                state = state,
                contentPadding = contentPadding,
            ) {
                items(count = 5) {
                    Text(
                        "Text item $it",
                        modifier = Modifier.scrollTransform(this).animateItem()
                    )
                }
                items(count = 5) {
                    Button(onClick = {}, modifier = Modifier.fillMaxWidth().animateItem()) {
                        Text("Item $it")
                    }
                }
            }
        }
    }
}
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.ListHeader
import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.scrollTransform

val allIngredients = listOf("2 eggs", "tomato", "cheese", "bread")
val state = rememberTransformingLazyColumnState()
val coroutineScope = rememberCoroutineScope()
AppScaffold {
    ScreenScaffold(
        state,
        contentPadding = PaddingValues(horizontal = 10.dp, vertical = 20.dp),
        edgeButton = {
            EdgeButton(onClick = { coroutineScope.launch { state.scrollToItem(1) } }) {
                Text("To top")
            }
        }
    ) { contentPadding ->
        TransformingLazyColumn(
            state = state,
            contentPadding = contentPadding,
            modifier = Modifier.background(MaterialTheme.colorScheme.background)
        ) {
            item(contentType = "header") {
                // No modifier is applied - no Material 3 Motion.
                ListHeader { Text("Ingredients") }
            }

            items(allIngredients, key = { it }) { ingredient ->
                Text(
                    ingredient,
                    color = MaterialTheme.colorScheme.onSurface,
                    style = MaterialTheme.typography.bodyLarge,
                    modifier =
                        Modifier.fillMaxWidth()
                            // Apply Material 3 Motion transformations.
                            .scrollTransform(
                                this,
                                backgroundColor = MaterialTheme.colorScheme.surfaceContainer,
                                shape = MaterialTheme.shapes.small
                            )
                            .padding(10.dp)
                )
            }
        }
    }
}
Parameters
scope: TransformingLazyColumnItemScope

The TransformingLazyColumnItemScope provides access to the item's index and key.

backgroundColor: Color

Color of the background.

shape: Shape = RectangleShape

Shape of the background.

@Composable
fun Modifier.scrollTransform(
    scope: TransformingLazyColumnItemScope,
    shape: Shape,
    painter: Painter,
    border: BorderStroke? = null
): Modifier

A modifier that enables Material3 Motion transformations for content within a TransformingLazyColumn item.

This modifier calculates and applies transformations to the content and background based on the TransformingLazyColumnItemScrollProgress of the item inside the TransformingLazyColumnItemScope. It adjusts the height, position, applies scaling and morphing effects as the item scrolls.

When ReduceMotion is enabled, this modifier will not apply any transformations.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.LocalReduceMotion
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.EdgeButtonSize
import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.scrollTransform

var enableReduceMotion by remember { mutableStateOf(true) }
val state = rememberTransformingLazyColumnState()
AppScaffold {
    ScreenScaffold(
        state,
        contentPadding = PaddingValues(horizontal = 10.dp, vertical = 20.dp),
        modifier = Modifier.background(MaterialTheme.colorScheme.background),
        edgeButton = {
            EdgeButton(
                onClick = { enableReduceMotion = !enableReduceMotion },
                buttonSize = EdgeButtonSize.Large
            ) {
                Text("Toggle reduce motion")
            }
        }
    ) { contentPadding ->
        CompositionLocalProvider(LocalReduceMotion provides enableReduceMotion) {
            TransformingLazyColumn(
                state = state,
                contentPadding = contentPadding,
            ) {
                items(count = 5) {
                    Text(
                        "Text item $it",
                        modifier = Modifier.scrollTransform(this).animateItem()
                    )
                }
                items(count = 5) {
                    Button(onClick = {}, modifier = Modifier.fillMaxWidth().animateItem()) {
                        Text("Item $it")
                    }
                }
            }
        }
    }
}
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.scrollTransform

val state = rememberTransformingLazyColumnState()
val coroutineScope = rememberCoroutineScope()
var expandedItemKey by remember { mutableStateOf(-1) }
var elements by remember { mutableStateOf(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) }

var nextElement = 10
fun addElement(index: Int) {
    elements =
        elements.subList(0, index) +
            listOf(nextElement++) +
            elements.subList(index, elements.count())
}

fun rainbowColor(progress: Float): Color {
    val hue = progress * 360f
    val saturation = 1f
    val value = 1f

    return Color(android.graphics.Color.HSVToColor(floatArrayOf(hue, saturation, value)))
}

AppScaffold {
    ScreenScaffold(
        state,
        edgeButton = {
            EdgeButton(
                onClick = {
                    addElement(elements.count())
                    coroutineScope.launch { state.scrollToItem(elements.count() - 1) }
                }
            ) {
                Text("Add item")
            }
        }
    ) { contentPadding ->
        val random = remember { Random }
        TransformingLazyColumn(
            state = state,
            contentPadding = contentPadding,
            modifier = Modifier.background(MaterialTheme.colorScheme.background)
        ) {
            items(elements, key = { it }) {
                val index = elements.indexOf(it)
                Column(
                    modifier =
                        Modifier.fillMaxWidth()
                            .scrollTransform(
                                this,
                                backgroundColor = MaterialTheme.colorScheme.surfaceContainer,
                                shape = MaterialTheme.shapes.medium
                            )
                            .animateItem()
                            .padding(5.dp)
                            .clickable {
                                elements =
                                    elements.subList(0, index) +
                                        elements.subList(index + 1, elements.count())
                            }
                ) {
                    Row(
                        verticalAlignment = CenterVertically,
                        horizontalArrangement = spacedBy(2.dp)
                    ) {
                        Text(
                            "Item $it",
                            color = MaterialTheme.colorScheme.onSurface,
                            style = MaterialTheme.typography.bodyLarge,
                            modifier = Modifier.weight(1f).fillMaxHeight()
                        )
                        Text("^", Modifier.clickable { addElement(index) })
                        Box(
                            Modifier.size(25.dp)
                                .drawWithContent {
                                    with(scrollProgress) {
                                        if (isUnspecified) {
                                            return@with
                                        }
                                        drawContent()
                                        val colorProgress =
                                            (topOffsetFraction + bottomOffsetFraction) / 2f
                                        val r = size.height / 2f
                                        drawCircle(
                                            rainbowColor(colorProgress),
                                            radius = r,
                                            center = Offset(size.width - r, r)
                                        )
                                        drawCircle(
                                            rainbowColor(random.nextFloat()),
                                            radius = r / 8,
                                            center = Offset(size.width - r, r)
                                        )
                                    }
                                }
                                .clickable {
                                    expandedItemKey =
                                        if (expandedItemKey == it) -1
                                        else {
                                            coroutineScope.launch { state.scrollToItem(index) }
                                            it
                                        }
                                }
                        )
                    }
                    AnimatedVisibility(expandedItemKey == it) {
                        // Expanded content goes here.
                        Box(modifier = Modifier.fillMaxWidth().height(100.dp))
                    }
                }
            }
        }
    }
}
Parameters
scope: TransformingLazyColumnItemScope

The TransformingLazyColumnItemScope provides access to the item's index and key.

shape: Shape

Shape of the background.

painter: Painter

Painter to use for the background.

border: BorderStroke? = null

Border to draw around the background, or null if no border is needed.

targetMorphingHeight

fun Modifier.targetMorphingHeight(scope: TransformingLazyColumnItemScope): Modifier

This modifier provides the height of the target composable to the scrollTransform during a morph transition and represents minimum height of the item when morphed.

Should be applied to a single child element or none at all (in which case, the morph effect is disabled). When applied to multiple child elements, the last placed child's height we be used for morphing.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.ListHeader
import androidx.wear.compose.material3.MaterialTheme
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.scrollTransform
import androidx.wear.compose.material3.lazy.targetMorphingHeight

data class MenuItem(val title: String, val price: Float)

val drinks =
    listOf(
        MenuItem("Cappuccino", 2.5f),
        MenuItem("Late", 3f),
        MenuItem("Flat White", 3.2f),
        MenuItem("Americano", 1.5f),
        MenuItem("Black tea", 2f),
        MenuItem("London fog", 2.6f),
    )
val state = rememberTransformingLazyColumnState()
val coroutineScope = rememberCoroutineScope()
AppScaffold {
    ScreenScaffold(
        state,
        contentPadding = PaddingValues(horizontal = 10.dp),
        edgeButton = {
            EdgeButton(
                onClick = {
                    coroutineScope.launch {
                        // Scroll to the first non-header item.
                        state.scrollToItem(1)
                    }
                }
            ) {
                Text("To top")
            }
        }
    ) { contentPadding ->
        TransformingLazyColumn(
            state = state,
            contentPadding = contentPadding,
            modifier = Modifier.background(MaterialTheme.colorScheme.background),
        ) {
            item(contentType = "header") {
                // No modifier is applied - no Material 3 Motion transformations.
                ListHeader { Text("Drinks", style = MaterialTheme.typography.labelLarge) }
            }
            items(drinks, key = { it.title }) { notification ->
                Column(
                    modifier =
                        Modifier.fillMaxWidth()
                            // Apply Material 3 Motion effect.
                            .scrollTransform(
                                this@items,
                                backgroundColor = Color.DarkGray,
                                shape = RoundedCornerShape(20.dp),
                            )
                            .padding(horizontal = 10.dp)
                ) {
                    Text(
                        notification.title,
                        fontWeight = FontWeight.Bold,
                        style = MaterialTheme.typography.labelLarge,
                        // Morphing is focusing on the title.
                        modifier = Modifier.targetMorphingHeight(this@items)
                    )
                    // Price is revealed after the morph.
                    Text("$${notification.price}")
                }
            }
        }
    }
}
Parameters
scope: TransformingLazyColumnItemScope

The TransformingLazyColumnItemScope provides access to the item's index and key.