What You Will Build

A social media feed screen with user avatars, post content, like/comment/share action rows, and post timestamps. This recreates the core Instagram feed layout pattern that applies to any social networking, news feed, or community app.

Why Social Feed Layouts Are Essential Knowledge

The avatar + content + action bar pattern is the most replicated UI structure in mobile development. Understanding how to compose it from nested Row/Column blocks with proper spacing and alignment transfers directly to chat apps, comment sections, and notification lists.

The Post Data Model

data class Post(
    val user: String,
    val content: String,
    val likes: Int
)

val posts = listOf(
    Post("Alice",
        "Beautiful sunset today! The sky was painted in shades of orange and pink.",
        142),
    Post("Bob",
        "Just finished a great workout at the gym. Feeling energized!",
        89),
    Post("Carol",
        "New recipe tried today - homemade pasta from scratch. Delicious!",
        234)
)

The Post Card with Avatar

Column(Modifier.padding(16.dp)) {
    // User header
    Row(verticalAlignment = Alignment.CenterVertically) {
        Box(
            Modifier
                .size(40.dp)
                .clip(CircleShape)
                .background(MaterialTheme.colorScheme.primaryContainer),
            contentAlignment = Alignment.Center
        ) {
            Text(
                post.user.first().toString(),
                fontWeight = FontWeight.Bold
            )
        }
        Spacer(Modifier.width(12.dp))
        Column {
            Text(post.user, fontWeight = FontWeight.Bold)
            Text("2h ago", fontSize = 12.sp,
                color = MaterialTheme.colorScheme.onSurfaceVariant)
        }
    }

    Spacer(Modifier.height(8.dp))
    Text(post.content)
    Spacer(Modifier.height(8.dp))

    // Action row
    Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            Icon(Icons.Default.FavoriteBorder, "Like",
                modifier = Modifier.size(20.dp))
            Spacer(Modifier.width(4.dp))
            Text("${'$'}{post.likes}")
        }
        Row(verticalAlignment = Alignment.CenterVertically) {
            Icon(Icons.Default.ChatBubbleOutline, "Comment",
                modifier = Modifier.size(20.dp))
            Spacer(Modifier.width(4.dp))
            Text("Reply")
        }
        Icon(Icons.Default.Share, "Share",
            modifier = Modifier.size(20.dp))
    }

    HorizontalDivider(Modifier.padding(top = 12.dp))
}

Tips and Pitfalls

  • CircleShape avatar with initial letter is a clean placeholder when no profile image is available. Use post.user.first().toString().
  • HorizontalDivider between posts creates visual separation in the feed. This is preferred over card elevation for feed-style layouts.
  • FavoriteBorder vs Favorite: Use the outline icon for unliked state and filled for liked state, toggled with a boolean.
  • Use LazyColumn (not Column with verticalScroll) for feeds with many items to enable view recycling.

Minimum SDK: API 24+ with Compose BOM 2024.01+

Get New Tutorials by Email

No spam. Just clear, practical breakdowns you can apply right away.

Enjoy this tutorial?

Get new practical tech tutorials in your inbox.