Build apps faster with our new App builder! Check it out →

ScalingLazyColumn

Android

Component in Wear Material Compose

A scrolling scaling/fisheye list component that forms a key part of the Wear Material Design language. Provides scaling and transparency effects to the content items.

[ScalingLazyColumn] is designed to be able to handle potentially large numbers of content items. Content items are only materialized and composed when needed.

If scaling/fisheye functionality is not required then a [LazyColumn] should be considered instead to avoid any overhead of measuring and calculating scaling and transparency effects for the content items.

Last updated:

Installation

dependencies {
   implementation("androidx.wear.compose:compose-material:1.5.0-alpha04")
}

Overloads

@Deprecated(
    "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
)
@Composable
fun ScalingLazyColumn(
    modifier: Modifier = Modifier,
    state: ScalingLazyListState = rememberScalingLazyListState(),
    contentPadding: PaddingValues = PaddingValues(horizontal = 10.dp),
    reverseLayout: Boolean = false,
    verticalArrangement: Arrangement.Vertical =
        Arrangement.spacedBy(
            space = 4.dp,
            alignment = if (!reverseLayout) Alignment.Top else Alignment.Bottom
        ),
    horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
    flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
    userScrollEnabled: Boolean = true,
    scalingParams: ScalingParams = ScalingLazyColumnDefaults.scalingParams(),
    anchorType: ScalingLazyListAnchorType = ScalingLazyListAnchorType.ItemCenter,
    autoCentering: AutoCenteringParams? = AutoCenteringParams(),
    content: ScalingLazyListScope.() -> Unit
)

Parameters

namedescription
modifierThe modifier to be applied to the component
stateThe state of the component
contentPaddingThe padding to apply around the contents
reverseLayoutreverse the direction of scrolling and layout, when true items will be composed from the bottom to the top
verticalArrangementThe vertical arrangement of the layout's children. This allows us to add spacing between items and specify the arrangement of the items when we have not enough of them to fill the whole minimum size
horizontalAlignmentthe horizontal alignment applied to the items
flingBehaviorLogic describing fling behavior. If snapping is required use [ScalingLazyColumnDefaults.snapFlingBehavior].
userScrollEnabledwhether the scrolling via the user gestures or accessibility actions is allowed. You can still scroll programmatically using the state even when it is disabled.
scalingParamsThe parameters to configure the scaling and transparency effects for the component
anchorTypeHow to anchor list items to the center-line of the viewport
autoCenteringAutoCenteringParams parameter to control whether space/padding should be automatically added to make sure that list items can be scrolled into the center of the viewport (based on their [anchorType]). If non-null then space will be added before the first list item, if needed, to ensure that items with indexes greater than or equal to the itemIndex (offset by itemOffset pixels) will be able to be scrolled to the center of the viewport. Similarly space will be added at the end of the list to ensure that items can be scrolled up to the center. If null no automatic space will be added and instead the developer can use [contentPadding] to manually arrange the items.

Code Examples

SimpleScalingLazyColumn

@Composable
fun SimpleScalingLazyColumn() {
    ScalingLazyColumn(modifier = Modifier.fillMaxWidth()) {
        item { ListHeader { Text(text = "List Header") } }
        items(20) {
            Chip(
                onClick = {},
                label = { Text("List item $it") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
    }
}

ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo

@Composable
fun ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo() {
    val coroutineScope = rememberCoroutineScope()
    val itemSpacing = 6.dp
    // Line up the gap between the items on the center-line
    val scrollOffset = with(LocalDensity.current) { -(itemSpacing / 2).roundToPx() }
    val state =
        rememberScalingLazyListState(
            initialCenterItemIndex = 1,
            initialCenterItemScrollOffset = scrollOffset
        )

    ScalingLazyColumn(
        modifier = Modifier.fillMaxWidth(),
        anchorType = ScalingLazyListAnchorType.ItemStart,
        verticalArrangement = Arrangement.spacedBy(itemSpacing),
        state = state,
        autoCentering = AutoCenteringParams(itemOffset = scrollOffset)
    ) {
        item { ListHeader { Text(text = "List Header") } }
        items(20) {
            Chip(
                onClick = {
                    coroutineScope.launch {
                        // Add +1 to allow for the ListHeader
                        state.animateScrollToItem(it + 1, scrollOffset)
                    }
                },
                label = { Text("List item $it") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
    }
}

SimpleScalingLazyColumnWithSnap

@Composable
fun SimpleScalingLazyColumnWithSnap() {
    val state = rememberScalingLazyListState()
    ScalingLazyColumn(
        modifier = Modifier.fillMaxWidth(),
        state = state,
        flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(state = state)
    ) {
        item { ListHeader { Text(text = "List Header") } }
        items(20) {
            Chip(
                onClick = {},
                label = { Text("List item $it") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
    }
}

SimpleScalingLazyColumnWithContentPadding

@Composable
fun SimpleScalingLazyColumnWithContentPadding() {
    ScalingLazyColumn(
        modifier = Modifier.fillMaxWidth(),
        contentPadding = PaddingValues(top = 20.dp, bottom = 20.dp),
        autoCentering = null
    ) {
        item { ListHeader { Text(text = "List Header") } }
        items(20) {
            Chip(
                onClick = {},
                label = { Text("List item $it") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
    }
}
by @alexstyl