
In this article, we’ll learn how to implement the time picker in Material 3 Jetpack Compose.
Prerequisites:
What is a Time Picker?
A time picker is a UI element that allows users to select a time. It looks like this:

Let’s see how to implement it in the Android Studio.
First, create an empty Compose project and open the MainActivity.kt. Create a MyUI() composable and call it from the onCreate() method. We’ll write our code in it.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TimePicker
import androidx.compose.material3.TimePickerLayoutType
import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
MyUI()
}
}
}
}
}
}
@Composable
fun MyUI() {
}
Material 3 Jetpack Compose provides TimePicker API. It was added in version 1.1.0.
@Composable
@ExperimentalMaterial3Api
fun TimePicker(
state: TimePickerState,
modifier: Modifier = Modifier,
colors: TimePickerColors = TimePickerDefaults.colors(),
layoutType: TimePickerLayoutType = TimePickerDefaults.layoutType(),
)
state – This is to manage the state of the time picker.
modifier – We can modify the layout of the time picker.
colors – The colors of the time picker in different states.
layoutType – Type of the layout. It will change the position and sizing of the different components of the time picker.
Simple Time Picker:
The state is a mandatory parameter. We can get the state from the rememberTimePickerState() method.
@Composable
@ExperimentalMaterial3Api
fun rememberTimePickerState(
initialHour: Int = 0,
initialMinute: Int = 0,
is24Hour: Boolean = is24HourFormat,
): TimePickerState
initialHour – Starting hour to be displayed in the time picker. It ranges from 0 to 23.
initialMinute – Starting minute to be displayed in the time picker. It ranges from 0 to 59.
is24Hour – The format for this time picker. false for the 12-hour format with an AM/PM toggle or true for the 24-hour format without the toggle. Defaults to follow system setting.
Example:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyUI() {
val timePickerState = rememberTimePickerState()
TimePicker(state = timePickerState)
Text(text = "Selected H:M = ${timePickerState.hour} : ${timePickerState.minute}")
}
Output:

It is just a plain time picker. Let’s put it inside a dialog.
Time Picker with Dialog:
We can use the Material 3 dialog for the time picker.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyUI() {
var selectedHour by remember {
mutableIntStateOf(0) // or use mutableStateOf(0)
}
var selectedMinute by remember {
mutableIntStateOf(0) // or use mutableStateOf(0)
}
var showDialog by remember {
mutableStateOf(false)
}
val timePickerState = rememberTimePickerState(
initialHour = selectedHour,
initialMinute = selectedMinute
)
if (showDialog) {
AlertDialog(
modifier = Modifier
.fillMaxWidth()
.background(
color = MaterialTheme.colorScheme.surface,
shape = RoundedCornerShape(size = 12.dp)
),
onDismissRequest = { showDialog = false }
) {
Column(
modifier = Modifier
.background(
color = Color.LightGray.copy(alpha = 0.3f)
)
.padding(top = 28.dp, start = 20.dp, end = 20.dp, bottom = 12.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
// time picker
TimePicker(state = timePickerState)
// buttons
Row(
modifier = Modifier
.padding(top = 12.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.End
) {
// dismiss button
TextButton(onClick = { showDialog = false }) {
Text(text = "Dismiss")
}
// confirm button
TextButton(
onClick = {
showDialog = false
selectedHour = timePickerState.hour
selectedMinute = timePickerState.minute
}
) {
Text(text = "Confirm")
}
}
}
}
}
Button(
onClick = { showDialog = true }
) {
Text(text = "Show Time Picker")
}
Text(text = "Selected H:M = $selectedHour : $selectedMinute")
}
Output:

Related: Awesome Loading Dialog Made with Jetpack Compose
24 Hour Format:
We can change the time format using the rememberTimePickerState() method. Pass true to is24Hour for the 24-hour format.
val timePickerState = rememberTimePickerState(
initialHour = selectedHour,
initialMinute = selectedMinute,
is24Hour = true
)
TimePicker(state = timePickerState)
Output:

Time Picker Layouts:
There are two layouts – vertical and horizontal.
Vertical layout – It is used in the portrait mode. This is what we have seen in the previous outputs.
Horizontal layout – It is used in the landscape mode. It displays the toggle buttons and the clock side by side.
Let’s set the Horizontal layout.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyUI() {
var selectedHour by remember {
mutableIntStateOf(0) // or use mutableStateOf(0)
}
var selectedMinute by remember {
mutableIntStateOf(0) // or use mutableStateOf(0)
}
var showDialog by remember {
mutableStateOf(false)
}
val timePickerState = rememberTimePickerState(
initialHour = selectedHour,
initialMinute = selectedMinute
)
if (showDialog) {
AlertDialog(
modifier = Modifier
.fillMaxWidth()
.background(
color = MaterialTheme.colorScheme.surface,
shape = RoundedCornerShape(size = 12.dp)
),
onDismissRequest = { showDialog = false },
properties = DialogProperties(usePlatformDefaultWidth = false) // set this so that the dialog occupies the full width and height
) {
Column(
modifier = Modifier
.background(
color = Color.LightGray.copy(alpha = 0.3f)
)
.padding(top = 16.dp, start = 12.dp, end = 12.dp, bottom = 0.dp), // reduce the padding to make the dialog contents fit into the screen
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
// time picker
TimePicker(
state = timePickerState,
layoutType = TimePickerLayoutType.Horizontal // set horizontal layout
)
// buttons
Row(
modifier = Modifier
.padding(top = 6.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.Center // place buttons at the center
) {
// dismiss button
TextButton(onClick = { showDialog = false }) {
Text(text = "Dismiss")
}
// confirm button
TextButton(
onClick = {
showDialog = false
selectedHour = timePickerState.hour
selectedMinute = timePickerState.minute
}
) {
Text(text = "Confirm")
}
}
}
}
}
Button(
onClick = { showDialog = true }
) {
Text(text = "Show Time Picker")
}
Text(text = "Selected H:M = $selectedHour : $selectedMinute")
}
Change the screen orientation, you will see the following output.

TimeInput in Jetpack Compose:
There is another API called TimeInput. It allows the user to enter the time via two text fields, one for minutes and one for hours. It looks like this:

@Composable
@ExperimentalMaterial3Api
fun TimeInput(
state: TimePickerState,
modifier: Modifier = Modifier,
colors: TimePickerColors = TimePickerDefaults.colors(),
)
state – The state of the time input. We can use the previous rememberTimePickerState() here.
modifier – The Modifier to be applied to this time input.
colors – The colors of the time input at different states.
Example:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyUI() {
var selectedHour by remember {
mutableIntStateOf(0) // or use mutableStateOf(0)
}
var selectedMinute by remember {
mutableIntStateOf(0) // or use mutableStateOf(0)
}
var showDialog by remember {
mutableStateOf(false)
}
val timePickerState = rememberTimePickerState(
initialHour = selectedHour,
initialMinute = selectedMinute
)
if (showDialog) {
AlertDialog(
modifier = Modifier
.fillMaxWidth()
.background(
color = MaterialTheme.colorScheme.surface,
shape = RoundedCornerShape(size = 12.dp)
),
onDismissRequest = { showDialog = false }
) {
Column(
modifier = Modifier
.background(
color = Color.LightGray.copy(alpha = 0.3f)
)
.padding(top = 28.dp, start = 20.dp, end = 20.dp, bottom = 12.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
// time picker
TimeInput(state = timePickerState)
// buttons
Row(
modifier = Modifier
.padding(top = 12.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.End
) {
// dismiss button
TextButton(onClick = { showDialog = false }) {
Text(text = "Dismiss")
}
// confirm button
TextButton(
onClick = {
showDialog = false
selectedHour = timePickerState.hour
selectedMinute = timePickerState.minute
}
) {
Text(text = "Confirm")
}
}
}
}
}
Button(
onClick = { showDialog = true }
) {
Text(text = "Show Time Picker")
}
Text(text = "Selected H:M = $selectedHour : $selectedMinute")
}
Output:

This is all about the time picker APIs in Material 3 Jetpack Compose. I hope you have learned something new. If you have any doubts, leave a comment below.
Related Articles:
References: