What You Will Build
A social media feed screen with a notification bell in the top bar, user posts featuring circular avatar initials, content text, like counts, comment buttons, and share icons. Each post is separated by a Material 3 HorizontalDivider for clean visual separation.
Why This Pattern Matters
Every social app (Twitter/X, Instagram, LinkedIn) is built on a feed pattern. This project covers the essential building blocks: Scaffold with action icons, LazyColumn for efficient scrolling, avatar composables, and interaction row layouts.
Step 1: Scaffold with Notifications
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SocialAppScreen() {
Scaffold(
topBar = {
TopAppBar(
title = { Text("Social Feed") },
actions = {
IconButton(onClick = {}) {
Icon(Icons.Default.Notifications,
"Notifications")
}
}
)
}
) { padding ->
// Feed content
}
}
Step 2: Feed Post Layout
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))
// Post content
Text(post.content)
Spacer(Modifier.height(8.dp))
// Interactions
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
- LazyColumn vs Column: Always use LazyColumn for feeds that could grow. Column renders all items at once, causing memory issues with large datasets.
- Key parameter in items(): Add
key = { post.id }for stable identity during list updates, which enables item animations. - Icon sizing at 20.dp keeps interaction buttons small and unobtrusive while remaining tappable.
- Real app extension: Add pull-to-refresh with
pullToRefreshmodifier (Material 3) or the Accompanist library.