DEV Community

myougaTheAxo
myougaTheAxo

Posted on

SegmentedButton in Compose: iOS-Style Segment Control for Android

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)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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")
}
Enter fullscreen mode Exit fullscreen mode

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()
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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
    )
)
Enter fullscreen mode Exit fullscreen mode

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 remember with mutableIntStateOf for 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)