Time Picker in Material 3 Jetpack Compose (with Examples)

Jetpack Compose Material 3 Time Picker

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:

Time Picker Example

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:

Simple Material 3 Time Picker in Jetpack Compose

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:

Time Picker with Dialog

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:

24 Hour Format

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.

Horizontal Layout

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:

time input example
@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:

time input

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:

Leave a Comment