Computer scienceMobileJetpack ComposeComposablesMaterial

Checkbox, Radio Button, and Switch

10 minutes read

Checkbox, Radio Button, and Switch are essential components in Jetpack Compose for creating interactive and user-friendly interfaces in Android apps. These components allow users to make selections, toggle settings, and provide input in an intuitive and visually appealing way.

In this topic, you'll learn how to create and customize Checkbox, Radio Button, and Switch components using Jetpack Compose. You'll also discover how to handle user interaction, manage state, and integrate these components with other composables to build cohesive and functional user interfaces.

Checkbox

A Checkbox is a widely-used user interface element that allows users to make binary choices, typically representing a selection or deselection of an option.

Checkboxes are commonly seen in forms, settings, and task lists, where the user needs to select multiple options from a given set independently. For instance, a to-do list app might use checkboxes to mark tasks as completed, while a settings screen might use them to enable or disable various features.

In Jetpack Compose, implementing a Checkbox is straightforward. The basic Checkbox composable function requires a boolean state to determine whether the checkbox is checked or unchecked. To handle this state, we use remember and mutableStateOf from the Compose toolkit. Here's a simple example:

var isChecked by remember { mutableStateOf(false) }

Checkbox(
    checked = isChecked,
    onCheckedChange = { isChecked = it }
)

In this example, isChecked is a mutable state that holds the current state of the checkbox. The Checkbox composable reads this state with the checked parameter to determine whether it should be checked or unchecked. The onCheckedChange lambda updates the state whenever the user interacts with the checkbox, ensuring that the UI remains in sync with the underlying data. The output will be:

Checkbox

Three states Checkbox

The TriStateCheckbox is a unique checkbox variant in Jetpack Compose that offers three states: Checked, Unchecked, and Indeterminate. This "in-between" state is invaluable for scenarios involving hierarchical selections or multi-level checklists where a parent item's state depends on its children.

Imagine a file manager app where you can select folders containing multiple files. The indeterminate state ( ) would visually represent a folder where only some files are selected. This clear visual cue helps users understand the selection status at a glance.

Implementing a TriStateCheckbox is straightforward. You manage its state using remember and mutableStateOf, just like with regular checkboxes. The onClick action cycles through the three states, allowing users to toggle between them:

@Composable
fun TriStateCheckboxExample() {
    var state by remember { mutableStateOf(ToggleableState.Indeterminate) }

    TriStateCheckbox(
        state = state,
        onClick = {
            state = when (state) {
                ToggleableState.On -> ToggleableState.Off
                ToggleableState.Off -> ToggleableState.Indeterminate
                ToggleableState.Indeterminate -> ToggleableState.On
            }
        }
    )
}

Here we used the ToggleableState enum provided by Jetpack Compose to represent these three states. This enum offers three values: On (representing "Checked"), Off (representing "Unchecked"), and Indeterminate. By using ToggleableState to manage the state of your TriStateCheckbox, you ensure type-safe and readable code that accurately reflects the component's behavior.

Three states

Let's consider a more practical example that demonstrates the implementation of a multi-level selection list using TriStateCheckbox:

val parentState = remember { mutableStateOf(ToggleableState.Off) }
val childStates = remember {
    mutableStateListOf(ToggleableState.Off, ToggleableState.Off)
}

Column {
    Row(
        verticalAlignment = Alignment.CenterVertically
    ) {
        TriStateCheckbox(
            state = parentState.value,
            onClick = {
                val newState = when (parentState.value) {
                    ToggleableState.On -> ToggleableState.Off
                    ToggleableState.Off -> ToggleableState.On
                    ToggleableState.Indeterminate -> ToggleableState.On
                }
                parentState.value = newState
                childStates.fill(newState)
            }
        )
        Text("Parent")
    }
    
    childStates.forEachIndexed { index, state ->
        Row(
            verticalAlignment = Alignment.CenterVertically
        ) {
            Checkbox(
                checked = state == ToggleableState.On,
                onCheckedChange = { isChecked ->
                    childStates[index] =
                        if (isChecked) ToggleableState.On else ToggleableState.Off
                    parentState.value = when {
                        childStates.all { it == ToggleableState.On } -> ToggleableState.On
                        childStates.all { it == ToggleableState.Off } -> ToggleableState.Off
                        else -> ToggleableState.Indeterminate
                    }
                },
                modifier = Modifier.padding(start = 16.dp)
            )
            Text("Child ${index+1}")
        }
    }
}

In this example, the parentState represents the state of the TriStateCheckbox, while the list named childStates holds the state of each child Checkbox. The code ensures that the parent's state accurately reflects the selection status of its children, providing a seamless and intuitive user experience.

TriStateCheckbox

You can check the official documentation to explore another way to implement a multi-level selection list using TriStateCheckbox.

Radio Button

A Radio Button is a user interface element that allows users to select one option from a predefined set of mutually exclusive options. Unlike Checkboxes, where multiple selections are allowed, Radio Buttons enforce a single selection within a group. This makes them ideal for scenarios where only one choice is permitted, such as selecting a payment method, choosing a shipping option, or answering multiple-choice questions in a survey.

To create a basic Radio Button, you use the RadioButton composable function.

The RadioButton function requires a selected parameter to determine whether the Radio Button is selected and an onClick parameter to handle the selection change. Typically, you will manage the state of the Radio Button using remember and mutableStateOf to create a state variable that tracks the selected option.

Multiple radio buttons can be grouped using composables like Rowto allow the user to select a single option from a set of mutually exclusive options.

For example, consider a scenario where you want to create a survey form with Radio Button options for selecting a favorite programming language. You would define a state variable to store the selected language and use RadioButton composables to render each option. Here's a simple implementation:

var selectedLanguage by remember { mutableStateOf("Kotlin") }

Column {
    Text("Select your favorite programming language:")

    Row(
        verticalAlignment = Alignment.CenterVertically,
    ) {
        RadioButton(
            selected = selectedLanguage == "Kotlin",
            onClick = { selectedLanguage = "Kotlin" }
        )
        Text("Kotlin")

        Spacer(modifier = Modifier.width(24.dp))

        RadioButton(
            selected = selectedLanguage == "Java",
            onClick = { selectedLanguage = "Java" }
        )
        Text("Java")

        Spacer(modifier = Modifier.width(24.dp))

        RadioButton(
            selected = selectedLanguage == "Python",
            onClick = { selectedLanguage = "Python" }
        )
        Text("Python")
    }
}

In this example, the selectedLanguage state variable is used to track the selected option, and the onClick handlers update this variable accordingly.

Two radio buttons

Switch

A Switch is a UI component that allows users to toggle between two states: on and off. It is commonly used in settings screens where users can enable or disable features, such as turning on notifications or switching between dark and light modes. Switches provide a clear and intuitive way for users to control binary options in an application.

In Jetpack Compose, you can use the Switch composable function to create a basic switch. To handle the state of the switch, you can use the remember and mutableStateOf functions to create a state variable that keeps track of whether the switch is on or off. Here's a simple example:

var isEnabled by remember { mutableStateOf(false) }

Switch(
    checked = isEnabled,
    onCheckedChange = { isEnabled = it }
)

In this example, isEnabled is a state variable that holds the current state of the switch. The Switch composable takes two parameters: checked, which represents the current state, and onCheckedChange, which is a lambda function that updates the state when the switch is toggled. The result will look like this:

Switch

Customization

In Jetpack Compose, customization of UI components is a crucial aspect that enhances the user experience and aligns the application with its design guidelines. Here, we will explore how to style and theme Checkboxes, Radio Buttons, Switches, and TriStateCheckboxes.

  • Checkbox

Checkboxes in Jetpack Compose can be customized to fit the visual identity of your app. The Checkbox composable allows you to change its appearance using parameters such as colors.

By default, the Checkbox uses the Material Design theme colors, but you can override these using the CheckboxDefaults.colors method. For instance, you can set custom colors for the checked and unchecked states, as well as the checkmark color. Additionally, you can use the modifier parameter to apply padding, margins, or other layout modifications.

Checkbox(
    ...
    colors = CheckboxDefaults.colors(
        checkedColor = Color.Green,
        uncheckedColor = Color.Red,
        checkmarkColor = Color.White
    ),
    modifier = Modifier.padding(8.dp)
)

TriStateCheckbox can also be customized using CheckboxDefaults.colors. The color of the checkmark in the indeterminate state is defined by the checkmarkColor, while the fill color is defined by the checkedColor.

  • Radio Button

Radio Buttons can also be customized similarly. The RadioButton composable uses the colors parameter to define the color scheme. You can customize the selected and unselected colors using RadioButtonDefaults.colors. Furthermore, the modifier parameter allows you to apply additional styling such as padding, size adjustments, or other layout properties.

RadioButton(
    ...
    colors = RadioButtonDefaults.colors(
        selectedColor = Color.Blue,
        unselectedColor = Color.Gray
    ),
    modifier = Modifier.padding(8.dp)
)
  • Switch

Switches provide a way to toggle between two states and can be styled using the colors parameter. The SwitchDefaults.colors method allows you to set custom colors for the checked and unchecked thumb and track. This enables you to create a switch that matches your app's theme. The modifier parameter can be used to adjust layout properties such as padding and size.

Switch(
    ...
    colors = SwitchDefaults.colors(
        checkedThumbColor = Color.Yellow,
        uncheckedThumbColor = Color.Gray,
        checkedTrackColor = Color.Green,
        uncheckedTrackColor = Color.Red
    ),
    modifier = Modifier.padding(8.dp)
)

Conclusion

Checkbox , RadioButton , and Switch components are essential building blocks for creating interactive and user-friendly interfaces in Jetpack Compose. By understanding how to create, customize, and handle user interaction with these components, you can enhance the user experience and functionality of your Android apps.

Remember to:

  • Use the appropriate composable for each component (Checkbox, RadioButton, Switch)

  • Define and manage state variables using remember or rememberSaveable

  • Handle user interaction with callbacks like onCheckedChange and onClick

  • Integrate these components with other composables to create a cohesive UI

With your newfound knowledge of Checkbox , RadioButton , and Switch components in Jetpack Compose, you're ready to create dynamic and interactive user interfaces in your Android apps.

Let's reinforce your understanding by diving into some practical tasks and applying what you've learned!

6 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo