Visual Grouping with Card and Surface in Jetpack Compose

Creating Visual Structure: A Deep Dive into "Card" and "Surface"

You know how to lay out components and make them interactive. Now, let's focus on making them look good. "Card" and "Surface" are two fundamental Material Design composables that help you group content, create visual hierarchy, and give your app a clean, modern feel.


What is a "Surface"?

A Surface is a basic building block that represents a section of UI with its own:

  • Color: It typically draws a background color from your MaterialTheme.
  • Elevation: It can be elevated from the background, casting a shadow.
  • Shape: It can have its corners rounded.
  • Border: It can have a border.

Almost every visual element in Compose is built on or inside a Surface. A Button is a Surface. A TopAppBar is a Surface. It's the "material" on which you draw.


What is a "Card"?

A Card is simply a Surface that is pre-configured for the specific use case of displaying a "card" of content. It's a convenient shortcut with default styling that clearly separates a group of related content from the rest of the UI.

Think of a post on a social media feed or a product on an e-commerce site—each one is typically presented in its own Card.

@Composable
fun SimpleCardExample() {
    Card(
        // The modifier is used for sizing, margins, etc.
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        // Elevation adds a shadow, making the card appear to "float"
        elevation = CardDefaults.cardElevation(defaultElevation = 8.dp),
        // You can customize the shape of the card's corners
        shape = RoundedCornerShape(12.dp)
    ) {
        // You place the card's content inside its lambda
        Column(modifier = Modifier.padding(16.dp)) {
            Text(
                text = "This is a Card",
                style = MaterialTheme.typography.headlineSmall
            )
            Text(
                text = "It groups content and provides elevation.",
                style = MaterialTheme.typography.bodyMedium
            )
        }
    }
}

Combining Them for Great UI

The best UIs use these components together. For instance, a LazyColumn might display a list of Cards, and each Card might contain an Image and a Column of Texts.

@Composable
fun NewsArticleCard() {
    Card(
        modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
        elevation = CardDefaults.cardElevation(4.dp),
        onClick = { /* Handle click */ }
    ) {
        Column {
            Image(
                painter = painterResource(id = R.drawable.placeholder_image), // Placeholder
                contentDescription = "Article Thumbnail",
                modifier = Modifier
                    .fillMaxWidth()
                    .height(180.dp),
                contentScale = ContentScale.Crop // Fills the space
            )
            Column(modifier = Modifier.padding(16.dp)) {
                Text("Jetpack Compose News", style = MaterialTheme.typography.titleLarge)
                Text("Learn all about Card and Surface!", style = MaterialTheme.typography.bodySmall)
            }
        }
    }
}

Key Concepts Recap

  • Surface: The most fundamental material composable for drawing backgrounds, handling elevation, and shaping content.
  • Card: A specialized Surface with default styling that's perfect for grouping related content into a single, elevated unit.
  • Elevation: A key property of both that lifts the component off the background and casts a shadow, creating depth.
  • Hierarchy: Using these components effectively helps create a clear visual hierarchy, guiding the user's eye to what's important.

Popular posts from this blog

Foundations of Jetpack Compose and Kotlin