PlaceholderDefaults

@ExperimentalWearMaterialApi
object PlaceholderDefaults


Contains the default values used for providing placeholders.

There are three distinct but coordinated aspects to placeholders in Compose for Wear OS. Firstly placeholder Modifier.placeholder which is drawn over content that is not yet loaded. Secondly a placeholder background which provides a background brush to cover the usual background of containers such as Chip or Card until all of the content has loaded. Thirdly a placeholder shimmer effect Modifier.placeholderShimmer effect which runs in an animation loop while waiting for the data to load.

Summary

Public functions

Painter
@Composable
painterWithPlaceholderOverlayBackgroundBrush(
    placeholderState: PlaceholderState,
    painter: Painter,
    color: Color
)

Create a Painter that wraps another painter and overlays a placeholder background brush on top.

Painter
@Composable
placeholderBackgroundBrush(
    placeholderState: PlaceholderState,
    color: Color
)

Create a Painter that paints with a placeholder background brush.

ChipColors

Create a ChipColors that can be used for a Chip that is used as a placeholder drawn on top of another Chip.

ChipColors
@Composable
placeholderChipColors(
    originalChipColors: ChipColors,
    placeholderState: PlaceholderState,
    color: Color
)

Create a ChipColors that can be used in placeholder mode.

Public functions

painterWithPlaceholderOverlayBackgroundBrush

@Composable
fun painterWithPlaceholderOverlayBackgroundBrush(
    placeholderState: PlaceholderState,
    painter: Painter,
    color: Color = MaterialTheme.colors.surface
): Painter

Create a Painter that wraps another painter and overlays a placeholder background brush on top. If the placeholderState is PlaceholderState.isShowContent the original painter will be used. Otherwise the painter will be drawn and then a placeholder background will be drawn over it or a wipe-off brush will be used to reveal the background when the state is PlaceholderState.isWipeOff.

Parameters
placeholderState: PlaceholderState

the state of the placeholder

painter: Painter

the original painter that will be drawn over when in placeholder mode.

color: Color = MaterialTheme.colors.surface

the color to use for the placeholder background brush

placeholderBackgroundBrush

@Composable
fun placeholderBackgroundBrush(
    placeholderState: PlaceholderState,
    color: Color = MaterialTheme.colors.surface
): Painter

Create a Painter that paints with a placeholder background brush. If the placeholderState is PlaceholderState.isShowContent then a transparent background will be shown. Otherwise a placeholder background will be drawn or a wipe-off brush will be used to reveal the content underneath when PlaceholderState.isWipeOff is true.

Parameters
placeholderState: PlaceholderState

the state of the placeholder

color: Color = MaterialTheme.colors.surface

the color to use for the placeholder background brush

placeholderChipColors

@Composable
fun placeholderChipColors(
    placeholderState: PlaceholderState,
    color: Color = MaterialTheme.colors.surface
): ChipColors

Create a ChipColors that can be used for a Chip that is used as a placeholder drawn on top of another Chip. When not drawing a placeholder background brush the chip will be transparent allowing the contents of the chip below to be displayed.

Example of a Chip with icon and a primary and secondary labels that draws another Chip over the top of it when waiting for placeholder data to load and draws over the Chips normal background color with color as the placeholder background color which will be wiped away once all of the placeholder data is loaded:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PlaceholderDefaults
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.placeholder
import androidx.wear.compose.material.placeholderShimmer
import androidx.wear.compose.material.rememberPlaceholderState

var labelText by remember { mutableStateOf("") }
var secondaryLabelText by remember { mutableStateOf("") }
var iconResource: Int? by remember { mutableStateOf(null) }

val chipPlaceholderState = rememberPlaceholderState {
    labelText.isNotEmpty() && secondaryLabelText.isNotEmpty() && iconResource != null
}
Box {
    if (chipPlaceholderState.isShowContent || chipPlaceholderState.isWipeOff) {
        Chip(
            onClick = { /* Do something */ },
            enabled = true,
            label = {
                Text(
                    text = labelText,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )
            },
            secondaryLabel = {
                Text(
                    text = secondaryLabelText,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )
            },
            icon = {
                if (iconResource != null) {
                    Icon(
                        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                        contentDescription = "airplane",
                        modifier =
                            Modifier.wrapContentSize(align = Alignment.Center)
                                .size(ChipDefaults.IconSize)
                    )
                }
            },
            colors = ChipDefaults.gradientBackgroundChipColors(),
            modifier = Modifier.fillMaxWidth()
        )
    }
    if (!chipPlaceholderState.isShowContent) {
        Chip(
            onClick = { /* Do something */ },
            enabled = true,
            label = {
                Box(
                    modifier =
                        Modifier.fillMaxWidth()
                            .height(16.dp)
                            .padding(top = 1.dp, bottom = 1.dp)
                            .placeholder(placeholderState = chipPlaceholderState)
                )
            },
            secondaryLabel = {
                Box(
                    modifier =
                        Modifier.fillMaxWidth()
                            .height(16.dp)
                            .padding(top = 1.dp, bottom = 1.dp)
                            .placeholder(placeholderState = chipPlaceholderState)
                )
            },
            icon = {
                Box(
                    modifier =
                        Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState)
                )
                // Simulate the icon becoming ready after a period of time
                LaunchedEffect(Unit) {
                    delay(2000)
                    iconResource = R.drawable.ic_airplanemode_active_24px
                }
            },
            colors =
                PlaceholderDefaults.placeholderChipColors(
                    placeholderState = chipPlaceholderState
                ),
            modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
        )
    }
}
// Simulate data being loaded after a delay
LaunchedEffect(Unit) {
    delay(2500)
    secondaryLabelText = "A secondary label"
    delay(500)
    labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
    LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
Parameters
placeholderState: PlaceholderState

the current placeholder state.

color: Color = MaterialTheme.colors.surface

the color to use for the placeholder background brush.

placeholderChipColors

@Composable
fun placeholderChipColors(
    originalChipColors: ChipColors,
    placeholderState: PlaceholderState,
    color: Color = MaterialTheme.colors.surface
): ChipColors

Create a ChipColors that can be used in placeholder mode. This will provide the placeholder background effect that covers the normal chip background with a solid background of color when the placeholderState is set to show the placeholder and a wipe off gradient brush when the state is in wipe-off mode. If the state is PlaceholderState.isShowContent then the normal background will be used. All other colors will be delegated to originalChipColors.

Example of a Chip with icon and a label that put placeholders over individual content slots and then draws a placeholder shimmer over the result and draws over the Chips normal background color with color as the placeholder background color which will be wiped away once all of the placeholder data is loaded:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PlaceholderDefaults
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.placeholder
import androidx.wear.compose.material.placeholderShimmer
import androidx.wear.compose.material.rememberPlaceholderState

var labelText by remember { mutableStateOf("") }
var iconResource: Int? by remember { mutableStateOf(null) }
val chipPlaceholderState = rememberPlaceholderState {
    labelText.isNotEmpty() && iconResource != null
}

Chip(
    onClick = { /* Do something */ },
    enabled = true,
    label = {
        Text(
            text = labelText,
            maxLines = 2,
            overflow = TextOverflow.Ellipsis,
            modifier = Modifier.fillMaxWidth().placeholder(chipPlaceholderState)
        )
    },
    icon = {
        Box(modifier = Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState)) {
            if (iconResource != null) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                    contentDescription = "airplane",
                    modifier =
                        Modifier.wrapContentSize(align = Alignment.Center)
                            .size(ChipDefaults.IconSize)
                            .fillMaxSize(),
                )
            }
        }
    },
    colors =
        PlaceholderDefaults.placeholderChipColors(
            originalChipColors = ChipDefaults.primaryChipColors(),
            placeholderState = chipPlaceholderState
        ),
    modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
)
// Simulate content loading completing in stages
LaunchedEffect(Unit) {
    delay(2000)
    iconResource = R.drawable.ic_airplanemode_active_24px
    delay(1000)
    labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
    LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
Parameters
originalChipColors: ChipColors

the chip colors to use when not in placeholder mode.

placeholderState: PlaceholderState

the placeholder state of the component

color: Color = MaterialTheme.colors.surface

the color to use for the placeholder background brush