SurfaceTransformation

interface SurfaceTransformation


Object to be used to apply different transformation to the content and the background of the composable.

This interface allows you to customize the appearance of a surface by modifying the background painter and applying visual transformations to the content. This is useful for creating custom effects like scaling, rotation, or applying shaders.

Example usage with the Button:

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.SurfaceTransformation
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.rememberResponsiveTransformationSpec

val transformationSpec = rememberResponsiveTransformationSpec()

TransformingLazyColumn {
    items(count = 100) {
        Button(
            onClick = {},
            transformation = SurfaceTransformation(transformationSpec),
            modifier = Modifier.transformedHeight(transformationSpec::getTransformedHeight),
        ) {
            Text("Button #$it")
        }
    }
}

Example usage with the Card:

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.material3.SurfaceTransformation
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.TitleCard
import androidx.wear.compose.material3.lazy.rememberResponsiveTransformationSpec

val transformationSpec = rememberResponsiveTransformationSpec()
var expandedIndex by remember { mutableIntStateOf(-1) }

TransformingLazyColumn {
    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(transformationSpec::getTransformedHeight),
        ) {
            if (it == expandedIndex) {
                Text("Expanded content #$it")
            }
        }
    }
}

Example of adding support in a custom component:

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.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.SurfaceTransformation
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.lazy.rememberResponsiveTransformationSpec

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

val transformationSpec = rememberResponsiveTransformationSpec()

TransformingLazyColumn {
    items(count = 100) {
        MyCardComponent(
            "Message #$it",
            "This is a body",
            transformation = SurfaceTransformation(transformationSpec),
            modifier = Modifier.transformedHeight(transformationSpec::getTransformedHeight),
        )
    }
}

Summary

Public functions

Unit

Visual transformations to be applied to the item.

Painter
createBackgroundPainter(
    painter: Painter,
    shape: Shape,
    border: BorderStroke?
)

Returns a new painter to be used instead of painter which should react on a transformation.

Public functions

applyTransformation

fun GraphicsLayerScope.applyTransformation(): Unit

Visual transformations to be applied to the item.

This function is called within a GraphicsLayerScope, allowing you to use properties like scaleX, scaleY, rotationZ, alpha, and others to transform the content.

createBackgroundPainter

Added in 1.0.0-alpha34
fun createBackgroundPainter(
    painter: Painter,
    shape: Shape,
    border: BorderStroke? = null
): Painter

Returns a new painter to be used instead of painter which should react on a transformation.

This allows the transformation to modify the background 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: Painter

The original painter.

shape: Shape

The shape of the content to be used for clipping.

border: BorderStroke? = null

The border to be applied to the background.