# TransformationSpec

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


```
interface TransformationSpec
```

<br />

Known direct subclasses [ResponsiveTransformationSpec](https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/ResponsiveTransformationSpec)

|---|---|
| `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/ResponsiveTransformationSpec` | Version of `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec` that supports variable screen sizes. |

*** ** * ** ***

Defines visual transformations on the items of a `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)`.

When using this API, users need to make similar changes between all of the functions. For example, if `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec#getTransformedHeight(kotlin.Int,androidx.wear.compose.foundation.lazy.TransformingLazyColumnItemScrollProgress)` returns half of the size of the item, then transformation functions should do the same, scaling or cropping the item.

`https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec#getTransformedHeight(kotlin.Int,androidx.wear.compose.foundation.lazy.TransformingLazyColumnItemScrollProgress)` is called first, then the painter would be created and then container and content transformations are applied.

This shows how to create a custom transformation spec for the `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)`.

```kotlin
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.GraphicsLayerScope
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.TransformingLazyColumnItemScrollProgress
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.TransformationSpec
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight

val transformationSpec = rememberTransformationSpec()
val morphingTransformationSpec =
    object : TransformationSpec by transformationSpec {
        override fun GraphicsLayerScope.applyContainerTransformation(
            scrollProgress: TransformingLazyColumnItemScrollProgress
        ) {
            with(transformationSpec) { applyContainerTransformation(scrollProgress) }
            rotationX = (scrollProgress.topOffsetFraction - 0.5f).coerceIn(0f..1f) * 270f
        }
    }

TransformingLazyColumn(
    contentPadding = PaddingValues(20.dp),
    modifier = Modifier.background(Color.Black),
) {
    items(count = 100) { index ->
        Button(
            onClick = {},
            modifier =
                Modifier.fillMaxWidth()
                    .transformedHeight(this, morphingTransformationSpec)
                    .graphicsLayer {
                        with(morphingTransformationSpec) {
                            applyContainerTransformation(scrollProgress)
                        }
                    },
        ) {
            Text(
                "Item $index",
                modifier =
                    Modifier.graphicsLayer {
                        with(morphingTransformationSpec) {
                            applyContentTransformation(scrollProgress)
                        }
                    },
            )
        }
    }
}
```

This shows how to apply different `https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/CompositingStrategy` with `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec` for the `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)`.

```kotlin
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.CompositingStrategy.Companion.ModulateAlpha
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.TransformationSpec
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight

val transformationSpec = rememberTransformationSpec()

TransformingLazyColumn(
    contentPadding = PaddingValues(20.dp),
    modifier = Modifier.background(Color.Black),
) {
    items(count = 100) { index ->
        Button(
            onClick = {},
            modifier =
                Modifier.fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .graphicsLayer {
                        with(transformationSpec) {
                            applyContainerTransformation(scrollProgress)
                        }
                        // Using CompositingStrategy.ModulateAlpha can provide better
                        // performance when a container transformation involves alpha rendering,
                        // as it avoids an extra offscreen buffer.
                        //
                        // However, care must be taken with overlapping or transparent content
                        // inside the container. If the content itself uses alpha, ModulateAlpha
                        // can lead to multiple, incorrect alpha blending with the background
                        // (double-blending artifacts).
                        //
                        // To prevent this, the content's drawing layer must explicitly use
                        // CompositingStrategy.Offscreen to ensure internal elements are
                        // correctly pre-blended before the outer ModulateAlpha is applied.
                        compositingStrategy = ModulateAlpha
                    },
        ) {
            Text(
                text = "Item $index",
                modifier =
                    Modifier.graphicsLayer {
                        // Ensure content layer uses CompositingStrategy.Offscreen when
                        // container uses CompositingStrategy.ModulateAlpha.
                        // This composition is required to guarantee correct visual blending of
                        // content that contains internal alpha or complex blending.
                        // compositingStrategy is set to CompositingStrategy.Offscreen inside
                        // applyContentTransformation.
                        with(transformationSpec) { applyContentTransformation(scrollProgress) }
                    },
            )
        }
    }
}
```

This shows how to apply the `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec` to custom component inside `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)`.

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.ButtonDefaults
import androidx.wear.compose.material3.ButtonGroup
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.TransformationSpec
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight

// Use the spec derived from default small and large screen specs.
val transformationSpec = rememberTransformationSpec()

TransformingLazyColumn(
    contentPadding = PaddingValues(),
    modifier = Modifier.background(Color.Black),
) {
    items(count = 100) {
        val interactionSource1 = remember { MutableInteractionSource() }
        val interactionSource2 = remember { MutableInteractionSource() }

        ButtonGroup(
            modifier =
                Modifier.fillMaxWidth()
                    .graphicsLayer {
                        with(transformationSpec) {
                            applyContainerTransformation(scrollProgress)
                        }
                    }
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(
                        ButtonDefaults.minimumVerticalListContentPadding
                    )
        ) {
            Button(
                onClick = {},
                modifier = Modifier.animateWidth(interactionSource1),
                interactionSource = interactionSource1,
            ) {
                Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
                    Text(
                        "L",
                        modifier =
                            Modifier.graphicsLayer {
                                with(transformationSpec) {
                                    applyContentTransformation(scrollProgress)
                                }
                            },
                    )
                }
            }
            Button(
                onClick = {},
                modifier = Modifier.animateWidth(interactionSource2),
                interactionSource = interactionSource2,
            ) {
                Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
                    Text(
                        "R",
                        modifier =
                            Modifier.graphicsLayer {
                                with(transformationSpec) {
                                    applyContentTransformation(scrollProgress)
                                }
                            },
                    )
                }
            }
        }
    }
}
```

## Summary

| ### Public functions |
|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/GraphicsLayerScope.https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec#(androidx.compose.ui.graphics.GraphicsLayerScope).applyContainerTransformation(androidx.wear.compose.foundation.lazy.TransformingLazyColumnItemScrollProgress)( scrollProgress: https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnItemScrollProgress )` Visual transformations to be applied to the container of the item as it scrolls. |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/GraphicsLayerScope.https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec#(androidx.compose.ui.graphics.GraphicsLayerScope).applyContentTransformation(androidx.wear.compose.foundation.lazy.TransformingLazyColumnItemScrollProgress)( scrollProgress: https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnItemScrollProgress )` Visual transformations to be applied to the content of the item as it scrolls. |
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/painter/Painter` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformedContainerPainterScope.https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec#(androidx.wear.compose.material3.lazy.TransformedContainerPainterScope).createTransformedContainerPainter(androidx.compose.ui.graphics.painter.Painter,androidx.compose.ui.graphics.Shape,androidx.compose.foundation.BorderStroke)( painter: https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/painter/Painter, shape: https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/Shape, border: https://developer.android.com/reference/kotlin/androidx/compose/foundation/BorderStroke? )` Returns a new painter to be used instead of `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec#(androidx.wear.compose.material3.lazy.TransformedContainerPainterScope).createTransformedContainerPainter(androidx.compose.ui.graphics.painter.Painter,androidx.compose.ui.graphics.Shape,androidx.compose.foundation.BorderStroke)` which should react on a transformation. |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec#getTransformedHeight(kotlin.Int,androidx.wear.compose.foundation.lazy.TransformingLazyColumnItemScrollProgress)( measuredHeight: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html, scrollProgress: https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnItemScrollProgress )` Calculates the transformed height to be passed into `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnItemScope#(androidx.compose.ui.Modifier).transformedHeight(kotlin.Function2)` based on the parameters for the spec. |

## Public functions

### GraphicsLayerScope.applyContainerTransformation

Artifact: [androidx.wear.compose:compose-material3](https://developer.android.com/jetpack/androidx/releases/wear-compose) [View Source](https://cs.android.com/search?q=file:androidx/wear/compose/material3/lazy/TransformationSpec.kt+function:applyContainerTransformation) Added in [1.6.0](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.6.0)

```
fun GraphicsLayerScope.applyContainerTransformation(
    scrollProgress: TransformingLazyColumnItemScrollProgress
): Unit
```

Visual transformations to be applied to the container of the item as it scrolls.

| Parameters |
|---|---|
| `scrollProgress: https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnItemScrollProgress` | The scroll progress of the item. |

### GraphicsLayerScope.applyContentTransformation

Artifact: [androidx.wear.compose:compose-material3](https://developer.android.com/jetpack/androidx/releases/wear-compose) [View Source](https://cs.android.com/search?q=file:androidx/wear/compose/material3/lazy/TransformationSpec.kt+function:applyContentTransformation) Added in [1.6.0](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.6.0)

```
fun GraphicsLayerScope.applyContentTransformation(
    scrollProgress: TransformingLazyColumnItemScrollProgress
): Unit
```

Visual transformations to be applied to the content of the item as it scrolls.

| Parameters |
|---|---|
| `scrollProgress: https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnItemScrollProgress` | The scroll progress of the item. |

### TransformedContainerPainterScope.createTransformedContainerPainter

Artifact: [androidx.wear.compose:compose-material3](https://developer.android.com/jetpack/androidx/releases/wear-compose) [View Source](https://cs.android.com/search?q=file:androidx/wear/compose/material3/lazy/TransformationSpec.kt+function:createTransformedContainerPainter) Added in [1.5.0](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.5.0)

```
fun TransformedContainerPainterScope.createTransformedContainerPainter(
    painter: Painter,
    shape: Shape,
    border: BorderStroke?
): Painter
```

Returns a new painter to be used instead of `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/lazy/TransformationSpec#(androidx.wear.compose.material3.lazy.TransformedContainerPainterScope).createTransformedContainerPainter(androidx.compose.ui.graphics.painter.Painter,androidx.compose.ui.graphics.Shape,androidx.compose.foundation.BorderStroke)` which should react on a transformation.

| Parameters |
|---|---|
| `painter: https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/painter/Painter` | The painter to be transformed. This is the original `https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/painter/Painter` the component was trying to use. |
| `shape: https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/Shape` | The shape of the item's container. |
| `border: https://developer.android.com/reference/kotlin/androidx/compose/foundation/BorderStroke?` | The border of the item's container. |

### getTransformedHeight

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

```
fun getTransformedHeight(
    measuredHeight: Int,
    scrollProgress: TransformingLazyColumnItemScrollProgress
): Int
```

Calculates the transformed height to be passed into `https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnItemScope#(androidx.compose.ui.Modifier).transformedHeight(kotlin.Function2)` based on the parameters for the spec.

| Parameters |
|---|---|
| `measuredHeight: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | The height in pixels of the item returned during measurement. |
| `scrollProgress: https://developer.android.com/reference/kotlin/androidx/wear/compose/foundation/lazy/TransformingLazyColumnItemScrollProgress` | The scroll progress of the item. |