Master list item design patterns in Jetpack Compose with practical examples for every use case.
Basic ListItem Variants
@Composable
fun ListItemVariants() {
LazyColumn {
// Single-line ListItem
item {
ListItem(
headlineContent = { Text("Single line item") }
)
}
// Two-line ListItem
item {
ListItem(
headlineContent = { Text("Two line item") },
supportingContent = { Text("Supporting text") }
)
}
// Three-line ListItem
item {
ListItem(
headlineContent = { Text("Three line item") },
supportingContent = { Text("Supporting text that spans multiple lines") },
trailingContent = { Text("Trailing") }
)
}
}
}
ListItem with Leading and Trailing Content
@Composable
fun ListItemWithIcons() {
ListItem(
headlineContent = { Text("Settings") },
supportingContent = { Text("Customize your preferences") },
leadingContent = {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = "Settings",
modifier = Modifier.size(40.dp)
)
},
trailingContent = {
Icon(
imageVector = Icons.Default.ChevronRight,
contentDescription = "Navigate"
)
}
)
}
Avatar List Item with AsyncImage
@Composable
fun AvatarListItem(
name: String,
email: String,
avatarUrl: String
) {
ListItem(
headlineContent = { Text(name) },
supportingContent = { Text(email) },
leadingContent = {
AsyncImage(
model = avatarUrl,
contentDescription = name,
modifier = Modifier
.size(48.dp)
.clip(CircleShape),
contentScale = ContentScale.Crop
)
}
)
}
Card-Style Product List
@Composable
fun ProductListItem(
name: String,
price: String,
imageUrl: String,
onBuyClick: () -> Unit
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
AsyncImage(
model = imageUrl,
contentDescription = name,
modifier = Modifier
.size(80.dp)
.clip(RoundedCornerShape(8.dp)),
contentScale = ContentScale.Crop
)
Column(
modifier = Modifier
.weight(1f)
.padding(start = 12.dp)
) {
Text(name, style = MaterialTheme.typography.titleMedium)
Text(price, style = MaterialTheme.typography.bodySmall)
}
Button(onClick = onBuyClick) {
Text("Buy")
}
}
}
}
Checkbox Selection List
@Composable
fun SelectableListItem(
items: List<String>,
selectedItems: Set<String>,
onSelectionChange: (String, Boolean) -> Unit
) {
LazyColumn {
items(items) { item ->
ListItem(
headlineContent = { Text(item) },
leadingContent = {
Checkbox(
checked = item in selectedItems,
onCheckedChange = { isChecked ->
onSelectionChange(item, isChecked)
}
)
}
)
}
}
}
Sticky Header Sectioned List
@Composable
fun SectionedListWithHeaders(
sections: Map<String, List<String>>
) {
LazyColumn {
sections.forEach { (header, items) ->
stickyHeader {
Surface(
color = MaterialTheme.colorScheme.primaryContainer,
modifier = Modifier.fillMaxWidth()
) {
Text(
text = header,
modifier = Modifier.padding(16.dp),
style = MaterialTheme.typography.labelMedium
)
}
}
items(items) { item ->
ListItem(
headlineContent = { Text(item) },
modifier = Modifier.padding(horizontal = 16.dp)
)
}
}
}
}
Complete List with Multiple Patterns
@Composable
fun CompleteListExample() {
LazyColumn(modifier = Modifier.fillMaxSize()) {
stickyHeader {
Text("Available Users", modifier = Modifier.padding(16.dp))
}
items(20) { index ->
ListItem(
headlineContent = { Text("User $index") },
supportingContent = { Text("user$index@example.com") },
leadingContent = {
Surface(
shape = CircleShape,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(40.dp)
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxSize()
) {
Text("$index", color = Color.White)
}
}
},
trailingContent = {
IconButton(onClick = {}) {
Icon(Icons.Default.MoreVert, contentDescription = "More")
}
}
)
}
}
}
Build flexible, reusable list patterns that work for any data structure!
Get 8 Android app templates: Gumroad
Top comments (0)