# SurfaceTransformation

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/SurfaceTransformation.kt+class:androidx.wear.compose.material3.SurfaceTransformation) Added in [1.5.0](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.5.0)


```
interface SurfaceTransformation
```

<br />

*** ** * ** ***

Object to be used to apply different transformation to the content and the container (i.e. the background) of the composable.

This interface allows you to customize the appearance of a surface by modifying the container painter and applying visual transformations to the content. In this context, a surface is a container composable that displays content (which could use other Composables such as Icon, Text or Button) as well as a background typically drawn using a painter. This is useful for creating custom effects like scaling, rotation, or applying shaders.

Example usage with the `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/Button.composable#Button(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Function0,kotlin.String,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.wear.compose.material3.ButtonColors,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.layout.PaddingValues,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.wear.compose.material3.SurfaceTransformation,kotlin.Function1)`:

```kotlin
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.material3.Button
import androidx.wear.compose.material3.ButtonDefaults
import androidx.wear.compose.material3.SurfaceTransformation
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.ResponsiveTransformationSpec
import androidx.wear.compose.material3.lazy.TransformationVariableSpec
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight

val transformationSpec =
    rememberTransformationSpec(
        ResponsiveTransformationSpec.smallScreen(
            contentAlpha =
                TransformationVariableSpec(
                    0f,
                    transformationZoneEnterFraction = 0.4f,
                    transformationZoneExitFraction = 0.8f,
                ),
            containerAlpha = TransformationVariableSpec(0.3f),
        )
    )

TransformingLazyColumn {
    items(count = 100) {
        Button(
            onClick = {},
            transformation = SurfaceTransformation(transformationSpec),
            modifier =
                Modifier.transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(
                        ButtonDefaults.minimumVerticalListContentPadding
                    ),
        ) {
            Text("Button #$it")
        }
    }
}
```

![SurfaceTransformationButtonSample Composite
Image](https://developer.android.com/wear/images/design/WearComposeM3_SurfaceTransformationButtonSample_CompositeImage.png)

Example usage with the `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/Card.composable#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Function0,kotlin.String,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.wear.compose.material3.CardColors,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.layout.PaddingValues,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.wear.compose.material3.SurfaceTransformation,kotlin.Function1)`:

```kotlin
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.CardDefaults
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.SurfaceTransformation
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.TitleCard
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight

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

AppScaffold {
    ScreenScaffold(state) { contentPadding ->
        TransformingLazyColumn(state = state, contentPadding = contentPadding) {
            items(count = 100) {
                TitleCard(
                    onClick = { expandedIndex = if (expandedIndex == it) -1 else it },
                    title = { Text("Card #$it") },
                    subtitle = { Text("Subtitle #$it") },
                    transformation = SurfaceTransformation(transformationSpec),
                    modifier =
                        Modifier.transformedHeight(this, transformationSpec)
                            .minimumVerticalContentPadding(
                                CardDefaults.minimumVerticalListContentPadding
                            ),
                ) {
                    if (it == expandedIndex) {
                        Text("Expanded content #$it")
                    }
                }
            }
        }
    }
}
```

![SurfaceTransformationCardSample Composite
Image](https://developer.android.com/wear/images/design/WearComposeM3_SurfaceTransformationCardSample_CompositeImage.png)

Example of adding support in a custom component:

```kotlin
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.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.paint
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.material3.CardDefaults
import androidx.wear.compose.material3.SurfaceTransformation
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight

@Composable
fun MyCardComponent(
    title: String,
    body: String,
    transformation: SurfaceTransformation,
    modifier: Modifier = Modifier,
) {
    Column(
        modifier =
            modifier
                .fillMaxWidth()
                .graphicsLayer { with(transformation) { applyContainerTransformation() } }
                .paint(
                    transformation.createContainerPainter(
                        ColorPainter(color = Color.Gray),
                        shape = RoundedCornerShape(16.dp),
                    )
                )
                .padding(horizontal = 16.dp, vertical = 8.dp)
    ) {
        Text(title)
        Text(body)
    }
}

val transformationSpec = rememberTransformationSpec()

TransformingLazyColumn(contentPadding = PaddingValues(horizontal = 10.dp)) {
    items(count = 100) {
        MyCardComponent(
            "Message #$it",
            "This is a body",
            transformation = SurfaceTransformation(transformationSpec),
            modifier =
                Modifier.transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(
                        CardDefaults.minimumVerticalListContentPadding
                    ),
        )
    }
}
```

## 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/SurfaceTransformation#(androidx.compose.ui.graphics.GraphicsLayerScope).applyContainerTransformation()()` Visual transformations to be applied to the container of the item. |
| `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/SurfaceTransformation#(androidx.compose.ui.graphics.GraphicsLayerScope).applyContentTransformation()()` Visual transformations to be applied to the content of the item. |
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/painter/Painter` | `https://developer.android.com/reference/kotlin/androidx/wear/compose/material3/SurfaceTransformation#createContainerPainter(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/SurfaceTransformation#createContainerPainter(androidx.compose.ui.graphics.painter.Painter,androidx.compose.ui.graphics.Shape,androidx.compose.foundation.BorderStroke)` which should react on a transformation. |

## 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/SurfaceTransformation.kt+function:applyContainerTransformation) Added in [1.5.0](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.5.0)

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

Visual transformations to be applied to the container of the item.

This function is called within a `https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/GraphicsLayerScope`, allowing you to use properties like `scaleX`, `scaleY`, `rotationZ`, `alpha`, and others to transform the content.

### 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/SurfaceTransformation.kt+function:applyContentTransformation) Added in [1.5.0](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.5.0)

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

Visual transformations to be applied to the content of the item.

This function is called within a `https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/GraphicsLayerScope`, allowing you to use properties like `scaleX`, `scaleY`, `rotationZ`, `alpha`, and others to transform the content.

### createContainerPainter

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

```
fun createContainerPainter(
    painter: Painter,
    shape: Shape,
    border: BorderStroke? = null
): Painter
```

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

This allows the transformation to modify the container painter based on properties like the shape or border. For example, a transformation might apply a gradient that follows the shape of the surface.

| Parameters |
|---|---|
| `painter: https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/painter/Painter` | The original painter. |
| `shape: https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/Shape` | The shape of the content to be used for clipping. |
| `border: https://developer.android.com/reference/kotlin/androidx/compose/foundation/BorderStroke? = null` | The border to be applied to the container. |