Opinionated Wear Material 3 Card that offers a specific 5 slot layout to show information about an application, e.g. a notification. AppCards are designed to show interactive elements from multiple applications. They will typically be used by the system UI, e.g. for showing a list of notifications from different applications. However it could also be adapted by individual application developers to show information about different parts of their application.

Android
@Composable
public fun AppCard(
    appName: @Composable RowScope.() -> Unit,
    title: @Composable RowScope.() -> Unit,
    modifier: Modifier = Modifier,
    shape: Shape = CardDefaults.shape,
    colors: CardColors = CardDefaults.cardColors(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = CardDefaults.ContentPadding,
    transformation: SurfaceTransformation? = null,
    appImage: @Composable (RowScope.() -> Unit)? = null,
    time: @Composable (RowScope.() -> Unit)? = null,
    content: @Composable ColumnScope.() -> Unit,
): Unit

Parameters

appName A slot for displaying the application name, expected to be a single line of start aligned text of Typography.labelSmall
title A slot for displaying the title of the card, expected to be one or two lines of start aligned text of Typography.titleMedium
modifier Modifier to be applied to the card
shape Defines the card's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme
colors CardColors that will be used to resolve the colors used for this card. See CardDefaults.cardColors.
border A BorderStroke object which is used for drawing outlines.
contentPadding The spacing values to apply internally between the container and the content
transformation Transformation to be used when card appears inside a container that needs to dynamically change its content separately from the background.
appImage A slot for a small (CardDefaults.AppImageSizexCardDefaults.AppImageSize ) Image associated with the application.
time A slot for displaying the time relevant to the contents of the card, expected to be a short piece of end aligned text of Typography.labelSmall.
content The main slot for a content of this card
Android
@Composable
public fun AppCard(
    onClick: () -> Unit,
    appName: @Composable RowScope.() -> Unit,
    title: @Composable RowScope.() -> Unit,
    modifier: Modifier = Modifier,
    onLongClick: (() -> Unit)? = null,
    onLongClickLabel: String? = null,
    enabled: Boolean = true,
    shape: Shape = CardDefaults.shape,
    colors: CardColors = CardDefaults.cardColors(),
    border: BorderStroke? = null,
    contentPadding: PaddingValues = CardDefaults.ContentPadding,
    interactionSource: MutableInteractionSource? = null,
    transformation: SurfaceTransformation? = null,
    appImage: @Composable (RowScope.() -> Unit)? = null,
    time: @Composable (RowScope.() -> Unit)? = null,
    content: @Composable ColumnScope.() -> Unit,
): Unit

Parameters

onClick Will be called when the user clicks the card
appName A slot for displaying the application name, expected to be a single line of start aligned text of Typography.labelSmall
title A slot for displaying the title of the card, expected to be one or two lines of start aligned text of Typography.titleMedium
modifier Modifier to be applied to the card
onLongClick Called when this card is long clicked (long-pressed). When this callback is set, onLongClickLabel should be set as well.
onLongClickLabel Semantic / accessibility label for the onLongClick action.
enabled Controls the enabled state of the card. When false, this card will not be clickable and there will be no ripple effect on click. Wear cards do not have any specific elevation or alpha differences when not enabled - they are simply not clickable.
shape Defines the card's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme
colors CardColors that will be used to resolve the colors used for this card in different states. See CardDefaults.cardColors.
border A BorderStroke object which is used for drawing outlines.
contentPadding The spacing values to apply internally between the container and the content
interactionSource an optional hoisted MutableInteractionSource for observing and emitting Interactions for this card. You can use this to change the card's appearance or preview the card in different states. Note that if null is provided, interactions will still happen internally.
transformation Transformation to be used when card appears inside a container that needs to dynamically change its content separately from the background.
appImage A slot for a small (CardDefaults.AppImageSizexCardDefaults.AppImageSize ) Image associated with the application.
time A slot for displaying the time relevant to the contents of the card, expected to be a short piece of end aligned text of Typography.labelSmall.
content The main slot for a content of this card

Code Examples

AppCardSample

@Composable
fun AppCardSample() {
    AppCard(
        onClick = { /* Do something */ },
        appName = { Text("App name") },
        title = { Text("Card title") },
        time = { Text("Now") },
    ) {
        Text("Card content")
    }
}

AppCardWithIconSample

@Composable
fun AppCardWithIconSample() {
    AppCard(
        onClick = { /* Do something */ },
        appName = { Text("App name") },
        appImage = {
            Icon(
                painter = painterResource(id = android.R.drawable.star_big_off),
                contentDescription = "Star icon",
                modifier =
                    Modifier.size(CardDefaults.AppImageSize)
                        .wrapContentSize(align = Alignment.Center),
                tint = MaterialTheme.colorScheme.primary,
            )
        },
        title = { Text("Card title") },
        time = { Text("Now") },
    ) {
        Text("Card content")
    }
}

AppCardWithImageSample

@Composable
fun AppCardWithImageSample() {
    val configuration = LocalConfiguration.current
    // Add padding to the end of the image in order to maintain the correct proportions
    // between the image and the card.
    val imageEndPaddingDp = (0.15f * configuration.screenWidthDp).dp
    AppCard(
        onClick = { /* Do something */ },
        appName = { Text("App name") },
        appImage = {
            Icon(
                painter = painterResource(id = android.R.drawable.star_big_off),
                contentDescription = "Star icon",
                modifier =
                    Modifier.size(CardDefaults.AppImageSize)
                        .wrapContentSize(align = Alignment.Center),
                tint = MaterialTheme.colorScheme.primary,
            )
        },
        title = { Text("With image") },
        time = { Text("Now") },
    ) {
        Spacer(modifier = Modifier.height(4.dp))
        Row(modifier = Modifier.fillMaxWidth()) {
            Image(
                modifier =
                    Modifier.weight(1f).aspectRatio(16f / 9f).clip(RoundedCornerShape(16.dp)),
                painter = painterResource(id = R.drawable.card_content_image),
                contentScale = ContentScale.Crop,
                contentDescription = null,
            )
            Spacer(modifier = Modifier.width(imageEndPaddingDp))
        }
    }
}

NonClickableAppCardSample

@Composable
fun NonClickableAppCardSample() {
    AppCard(
        appName = { Text("App name") },
        title = { Text("Card title") },
        time = { Text("Now") },
    ) {
        Text("Non clickable card content")
    }
}

OutlinedAppCardSample

@Composable
fun OutlinedAppCardSample() {
    AppCard(
        onClick = { /* Do something */ },
        appName = { Text("App name") },
        appImage = {
            Icon(
                Icons.Filled.Favorite,
                contentDescription = "Favorite icon",
                modifier = Modifier.size(CardDefaults.AppImageSize),
            )
        },
        title = { Text("App card") },
        time = { Text("Now") },
        colors = CardDefaults.outlinedCardColors(),
        border = CardDefaults.outlinedCardBorder(),
    ) {
        Text("Card content")
    }
}