androidx.wear.compose.material3.lazy

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

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.

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.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
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,
        bottomButton = {
            EdgeButton(onClick = { coroutineScope.launch { state.scrollToItem(1) } }) {
                Text("To top")
            }
        }
    ) {
        TransformingLazyColumn(
            state = state,
            modifier =
                Modifier.background(MaterialTheme.colorScheme.background)
                    .padding(horizontal = 10.dp)
        ) {
            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.

@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. There is also an overload that applies the same visual transformations to the background.

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.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
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,
        bottomButton = {
            EdgeButton(onClick = { coroutineScope.launch { state.scrollToItem(1) } }) {
                Text("To top")
            }
        }
    ) {
        TransformingLazyColumn(
            state = state,
            modifier =
                Modifier.background(MaterialTheme.colorScheme.background)
                    .padding(horizontal = 10.dp)
        ) {
            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.

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.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
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,
        bottomButton = {
            EdgeButton(
                onClick = {
                    coroutineScope.launch {
                        // Scroll to the first non-header item.
                        state.scrollToItem(1)
                    }
                }
            ) {
                Text("To top")
            }
        }
    ) {
        TransformingLazyColumn(
            state = state,
            modifier =
                Modifier.background(MaterialTheme.colorScheme.background)
                    .padding(horizontal = 10.dp),
        ) {
            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.