# TransformingLazyColumnFirstLayoutItemProvider

Artifact: [androidx.wear.compose:compose-foundation](https://developer.android.com/jetpack/androidx/releases/wear-compose) [View Source](https://cs.android.com/search?q=file:androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.kt+class:androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider) Added in [1.7.0](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.7.0)


```
fun interface TransformingLazyColumnFirstLayoutItemProvider
```

<br />

*** ** * ** ***

Provides the first item to layout for `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumn.composable#TransformingLazyColumn(androidx.compose.ui.Modifier,androidx.wear.compose.foundation.lazy.TransformingLazyColumnState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior,androidx.compose.foundation.OverscrollEffect,androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider,kotlin.Function1)`.

During a measurement pass, `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumn.composable#TransformingLazyColumn(androidx.compose.ui.Modifier,androidx.wear.compose.foundation.lazy.TransformingLazyColumnState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior,androidx.compose.foundation.OverscrollEffect,androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider,kotlin.Function1)` uses the item returned by this provider as the initial placement reference. `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumn.composable#TransformingLazyColumn(androidx.compose.ui.Modifier,androidx.wear.compose.foundation.lazy.TransformingLazyColumnState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior,androidx.compose.foundation.OverscrollEffect,androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider,kotlin.Function1)` measures this item and places its requested `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo#itemEdge()` visual edge at the exact screen coordinate defined by `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo#offset()`, prior to accounting for active scroll deltas. Once this initial item is positioned, all other visible items are sequentially composed and placed above and below it.

Providing this interface allows controlling how the list places its children during content updates like additions, removals, or item size changes.

```kotlin
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastFirstOrNull
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider
import androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider.ItemEdge
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material.Text
import androidx.wear.compose.material3.CardDefaults
import androidx.wear.compose.material3.SurfaceTransformation
import androidx.wear.compose.material3.TitleCard
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight

val state = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
var expandedItemIndex by remember { mutableIntStateOf(-1) }

// This sample demonstrates how to use the provider API to control the direction of content
// shifting. By default, TransformingLazyColumn uses the center item as the layout reference.
// This means that if an item above the center expands, it pushes content upwards;
// if below, it pushes downwards.
//
// Here, we fix the Bottom/End edge of the clicked item regardless of its position on screen,
// so that when its animated content appears, the card predictably expands *upwards* every time.
val upwardExpandingItemProvider =
    remember(state) {
        TransformingLazyColumnFirstLayoutItemProvider { centerItem ->
            val item = expandedItemIndex

            // Yield to the standard layout behavior during active scrolls.
            // This avoids custom layout overhead and ensures the [TransformingLazyColumn]
            // tracks the user's scroll gesture using its default center layout reference.
            if (item == -1 || state.isScrollInProgress) {
                return@TransformingLazyColumnFirstLayoutItemProvider centerItem
            }

            // Look up the item's offset from state.layoutInfo (which holds the details
            // from the previous measure pass) to maintain its visual position in the current
            // pass.
            state.layoutInfo.visibleItems
                .fastFirstOrNull { visibleItem -> visibleItem.index == item }
                ?.let { visibleItem ->
                    TransformingLazyColumnFirstLayoutItemProvider.ItemInfo(
                        key = visibleItem.key,
                        index = visibleItem.index,
                        // Pin the bottom edge of the item
                        itemEdge = ItemEdge.End,
                        // Calculate the exact bottom offset from the previous pass
                        offset = visibleItem.offset + visibleItem.transformedHeight,
                    )
                } ?: centerItem
        }
    }

TransformingLazyColumn(
    state = state,
    contentPadding = PaddingValues(horizontal = 20.dp),
    firstLayoutItemProvider = upwardExpandingItemProvider,
) {
    items(count = 10, key = { it }) { cardIndex ->
        val isExpanded = expandedItemIndex == cardIndex
        TitleCard(
            onClick = { expandedItemIndex = cardIndex },
            modifier =
                Modifier.minimumVerticalContentPadding(
                        CardDefaults.minimumVerticalListContentPadding
                    )
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec),
            transformation = SurfaceTransformation(transformationSpec),
            title = { Text("Card $cardIndex") },
            subtitle = {
                AnimatedVisibility(isExpanded) { Text("Expanded content is available here") }
            },
            content = { Text("Tap to expand") },
        )
    }
}
```

## Summary

| ### Nested types |
|---|
| `value class https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemEdge` Represents the visual edge of `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` (Start or End) to which the offset refers. |
| `class https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` Holds information about the first item to layout in `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumn.composable#TransformingLazyColumn(androidx.compose.ui.Modifier,androidx.wear.compose.foundation.lazy.TransformingLazyColumnState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior,androidx.compose.foundation.OverscrollEffect,androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider,kotlin.Function1)`. |

| ### Public functions |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider#getFirstLayoutItem(androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider.ItemInfo)( centerItem: https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo )` Returns the `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` for the first item to layout in `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumn.composable#TransformingLazyColumn(androidx.compose.ui.Modifier,androidx.wear.compose.foundation.lazy.TransformingLazyColumnState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior,androidx.compose.foundation.OverscrollEffect,androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider,kotlin.Function1)`. |

## Public functions

### getFirstLayoutItem

Added in [1.7.0](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.7.0)

```
fun getFirstLayoutItem(
    centerItem: TransformingLazyColumnFirstLayoutItemProvider.ItemInfo
): TransformingLazyColumnFirstLayoutItemProvider.ItemInfo
```

Returns the `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` for the first item to layout in `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumn.composable#TransformingLazyColumn(androidx.compose.ui.Modifier,androidx.wear.compose.foundation.lazy.TransformingLazyColumnState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior,androidx.compose.foundation.OverscrollEffect,androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider,kotlin.Function1)`.

Note: This method is executed internally inside a `Snapshot.withoutReadObservation` block. Any Compose state reads performed inside this callback will not trigger layout observation.

If the returned `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` cannot be fully resolved (e.g., the key is not found or the index is out of bounds), `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumn.composable#TransformingLazyColumn(androidx.compose.ui.Modifier,androidx.wear.compose.foundation.lazy.TransformingLazyColumnState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior,androidx.compose.foundation.OverscrollEffect,androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider,kotlin.Function1)` falls back:

- If the `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo#key()` is not found, it falls back to the `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo#index()`.

- The final resolved index is coerced to stay within the valid list bounds.

| Parameters |
|---|---|
| `centerItem: https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` | The `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` that `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumn.composable#TransformingLazyColumn(androidx.compose.ui.Modifier,androidx.wear.compose.foundation.lazy.TransformingLazyColumnState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior,androidx.compose.foundation.OverscrollEffect,androidx.wear.compose.foundation.lazy.TransformingLazyColumnFirstLayoutItemProvider,kotlin.Function1)` would currently use for the first layout item if no provider is supplied. Returning this item preserves the default layout behavior. In most cases, this is the item closest to the center of the viewport from `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnLayoutInfo#visibleItems()`. |

| Returns |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` | The `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnFirstLayoutItemProvider.ItemInfo` of the item to use as the first item to layout. |