Jetpack Compose Time Picker (Material 3)

Time Pickers are very helpful if you are creating an application that requires users to select time. Jetpack Compose Time Picker reduces developer work as well as provides a better UI for the user to select a time from a time picker dialog. In this blog post, we will see how to implement a time picker in jetpack compose and how to customize a time picker.

Prerequisites:

Note:

We are using the latest version of Material 3 APIs and the BOM version given below:

implementation(platform("androidx.compose:compose-bom:2023.10.01"))

To go with the flow, we request you to update your BOM version in build.gradle.kts(Module:app) to the latest version or to that we are using.

What is Time Picker?

A time picker is a user interface (UI) element in software development that helps users select a specific time. They are designed to make it easier for users to input time accurately and efficiently, as typing out a time manually can be error-prone and less user-friendly.

The default Jetpack Compose Time Picker API provides two types of time picker:

  1. Vertical (Default)
  2. Horizontal

1. Vertical Time Picker

The default time picker API looks like this:

@Composable
@ExperimentalMaterial3Api
fun TimePicker(
    state: TimePickerState,
    modifier: Modifier = Modifier,
    colors: TimePickerColors = TimePickerDefaults.colors(),
    layoutType: TimePickerLayoutType = TimePickerDefaults.layoutType(),
)

Let’s break this function:

  • state – This manages the state of the time picker.
  • modifier – It applies different modifiers to this time picker.
  • colors – The colors variable helps in decorating the UI.
  • layoutType – This parameter makes our time picker UI vertical or horizontal.
val timeState = rememberTimePickerState(11, 30, false)
Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.Center
) {
    TimePicker(state = timeState)
    Text(text = "Time is ${timeState.hour} : ${timeState.minute}")
}

In the above code, we get the state from the rememberTimePickerState method. This method takes 3 mandatory parameters.

  • initialHour – This represents the default hour for the time picker. The default value is 0 and it ranges from 0 to 23.
  • initialMinute – This represents the default minute for the time picker. The default value is 0 and it ranges from 0 to 59.
  • is24Hour – It expects a boolean value where false is for the 12-hour format and true is for the 24-hour format. The default value is picked from your system setting.

Now after getting the state, we call TimePicker method inside a column and pass state to this method. Below this, we call the Text method and get the current hour and minute from timestate variable which is the state of TimePicker.

time picker

2. Horizontal Time Picker

In this case, we will give one more argument (layoutType) to TimePicker method.

val timeState = rememberTimePickerState(11, 30, false)
Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.Center
) {
    TimePicker(state = timeState, layoutType = TimePickerLayoutType.Horizontal)
    Text(text = "Time is ${timeState.hour} : ${timeState.minute} ")
}
horizontal

24 Hour Format

val timeState = rememberTimePickerState(11, 30, true)
Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    verticalArrangement = Arrangement.Center
) {
    TimePicker(state = timeState)
    Text(text = "Time is ${timeState.hour} : ${timeState.minute} ")
}
time picker in 24 hour format

Customize Time Picker

In this section, we use some of the available colour options. You can always check the details in the official documentation.

TimePicker(
    state = timeState,
    colors = TimePickerDefaults.colors(
        clockDialColor = Color.Cyan,
        clockDialSelectedContentColor = Color.Red,
        clockDialUnselectedContentColor = Color.Yellow,
        selectorColor = Color.Green,
        periodSelectorBorderColor = Color.Blue,
        periodSelectorSelectedContainerColor = Color.Magenta,
        periodSelectorSelectedContentColor = Color.Green,
        periodSelectorUnselectedContainerColor = Color.Cyan,
        periodSelectorUnselectedContentColor = Color.White,
        timeSelectorSelectedContainerColor = Color.Yellow,
        timeSelectorSelectedContentColor = Color.Magenta
    )
colored time picker

Time Picker with Alert Dialog

Now, we know how TimePicker works. We can launch it from an Alert Dialog. Let’s see how it works:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TimePickerWithDialog() {
    var selectedHour by remember { mutableIntStateOf(0) }
    var selectedMinute by remember { mutableIntStateOf(0) }
    var showDialog by remember { mutableStateOf(false) }
    val timeState = rememberTimePickerState(
        initialHour = selectedHour,
        initialMinute = selectedMinute
    )

    if (showDialog) {
        AlertDialog(
            onDismissRequest = { showDialog = false },
            modifier = Modifier.fillMaxWidth()
        ) {
            Column(
                modifier = Modifier
                    .background(color = Color.LightGray.copy(alpha = .3f))
                    .padding(top = 28.dp, start = 20.dp, end = 20.dp, bottom = 12.dp),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                TimePicker(state = timeState)
                Row(
                    modifier = Modifier
                        .padding(top = 12.dp)
                        .fillMaxWidth(), horizontalArrangement = Arrangement.End
                ) {
                    TextButton(onClick = { showDialog = false }) {
                        Text(text = "Dismiss")
                    }
                    TextButton(onClick = {
                        showDialog = false
                        selectedHour = timeState.hour
                        selectedMinute = timeState.minute
                    }) {
                        Text(text = "Confirm")
                    }
                }
            }
        }
    }

    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = { showDialog = true }) {
            Text(text = "Show Time Picker")
        }
        Text(text = "Time is ${timeState.hour} : ${timeState.minute}")
    }
}

In the above code, we create three variables using remember API so that they can survive the recomposition. These variable stores hour and minute value and showDialog stores a boolean value that is used to keep track dialog box is opened or not. The fourth variable stores the TimePicker state as described above.

Now, we call TimePicker in a column with two text buttons in a row layout and all this happens in the if statement only when the showDialog value is true.

Outside the if statement we call a button and text composable in the column layout. The clicking of the button changes the value of the showDialog variable to true which in turn runs the code of the if statement which shows the Alert Dialog. The Text shows the selected time on the screen.

Happy Composing 🙂

One thought on “Jetpack Compose Time Picker (Material 3)

Leave a Reply

Your email address will not be published. Required fields are marked *