SegmentedButton in Compose: iOS-Style Segment Control for Android
Material Design 3 introduces SegmentedButton components, bringing iOS-style segmented controls to Android. These interactive buttons let users switch between related options with a unified appearance and smooth transitions.
SingleChoiceSegmentedButtonRow
The simplest form allows selecting one option from a group:
var selectedIndex by remember { mutableIntStateOf(0) }
val options = listOf("Day", "Month", "Year")
SingleChoiceSegmentedButtonRow(
modifier = Modifier.fillMaxWidth()
) {
options.forEachIndexed { index, label ->
SegmentedButton(
selected = selectedIndex == index,
onClick = { selectedIndex = index },
shape = SegmentedButtonDefaults.itemShape(
index = index,
count = options.size
)
) {
Text(label)
}
}
}
MultiChoiceSegmentedButtonRow
For multiple selection scenarios, use MultiChoiceSegmentedButtonRow:
var selectedIndices by remember { mutableStateOf(setOf<Int>()) }
MultiChoiceSegmentedButtonRow(
modifier = Modifier.fillMaxWidth()
) {
options.forEachIndexed { index, label ->
SegmentedButton(
selected = index in selectedIndices,
onClick = {
selectedIndices = if (index in selectedIndices) {
selectedIndices - index
} else {
selectedIndices + index
}
},
shape = SegmentedButtonDefaults.itemShape(
index = index,
count = options.size
)
) {
Text(label)
}
}
}
Icons and Labels
Combine icons with labels for richer visual feedback:
SegmentedButton(
selected = isSelected,
onClick = { /* ... */ },
icon = {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = null
)
}
) {
Text("Settings")
}
Dynamic Content Switching
Use Crossfade for smooth transitions between segmented content:
var selectedTab by remember { mutableIntStateOf(0) }
Column {
SingleChoiceSegmentedButtonRow {
listOf("Profile", "Settings", "Billing").forEachIndexed { index, label ->
SegmentedButton(
selected = selectedTab == index,
onClick = { selectedTab = index },
shape = SegmentedButtonDefaults.itemShape(index, 3)
) {
Text(label)
}
}
}
Crossfade(selectedTab) { tab ->
when (tab) {
0 -> ProfileContent()
1 -> SettingsContent()
2 -> BillingContent()
}
}
}
Styling with SegmentedButtonDefaults
Customize appearance with Material 3 theming:
SegmentedButton(
selected = isSelected,
onClick = { /* ... */ },
colors = SegmentedButtonDefaults.colors(
activeContainerColor = MaterialTheme.colorScheme.primary,
inactiveContainerColor = Color.Transparent,
activeContentColor = MaterialTheme.colorScheme.onPrimary,
inactiveContentColor = MaterialTheme.colorScheme.onSurface
),
border = SegmentedButtonDefaults.borderStroke(
color = MaterialTheme.colorScheme.outline
)
)
Pro Tips
-
Shape management:
itemShape()automatically handles rounded corners for first/middle/last items - Accessibility: Always include meaningful labels or content descriptions for icons
-
State management: Use
rememberwithmutableIntStateOffor single selection,mutableStateOf<Set<Int>>for multiple - Performance: Avoid recomposing the entire row on every selection change
8 Android App Templates → https://myougatheax.gumroad.com
Top comments (0)