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+