0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ComposableでTimePickerDialogを作る

Last updated at Posted at 2024-01-21

Compose の Material3 には DatePickeDialog はあるのに TimePickerDialog が無い

Compose の Material3 には DatePickeDialog はあるのに TimePickerDialog は用意されていないようです。という事でもろもろ参考にしながら作ってみました。

プレビュー

こんな感じの見た目になります。

スクリーンショット 2024-01-22 053256.png

ComposeMaterial3 の導入

まずは、ComposeMaterial3 を入れます。

app/buid.bradle.kts
implementation("androidx.compose.material3:material3:1.1.2")

ダイアログ本体

続いてダイアログ本体を作ります。
現時点では、TimePicke 自体が Experimental 扱いのようなので、@OptIn アノテーションを付けています。
今回は AlertDialog にしましたが Dialog でも良いと思います。

CommonTimePickeDialog.kt
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CommonTimePickerDialog(
    timePickerState: TimePickerState = TimePickerState(0, 0, true),
    onDismiss: () -> Unit = {},
    onConfirm: (state: TimePickerState) -> Unit = {},
) {
    AlertDialog(
        onDismissRequest = onDismiss,
        properties = DialogProperties(
            usePlatformDefaultWidth = false
        ),
    ) {
        Surface(
            shape = MaterialTheme.shapes.extraLarge,
            tonalElevation = 6.dp,
            modifier = Modifier
                .width(IntrinsicSize.Min)
                .height(IntrinsicSize.Min)
                .background(
                    shape = MaterialTheme.shapes.extraLarge,
                    color = MaterialTheme.colorScheme.surface
                ),
        ) {
            Column(
                modifier = Modifier.padding(24.dp),
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(bottom = 20.dp),
                    text = stringResource(id = R.string.label_select_time),
                    style = MaterialTheme.typography.labelMedium
                )
                TimePicker(state = timePickerState)
                Row(
                    modifier = Modifier
                        .height(40.dp)
                        .fillMaxWidth()
                ) {
                    Spacer(modifier = Modifier.weight(1f))
                    Button(onClick = { onConfirm(timePickerState) }) {
                        Text(stringResource(id = R.string.label_ok))
                    }
                }
            }
        }
    }
}

呼び出し側

最後に呼び出し側を作ります。
今回はテキストフィールドをタップするとダイアログが開くようにしました。
こちらも、@OptIn アノテーションを付けています。

TimeSelector.kt
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TimeSelector(
    initialHour: Int = 0,
    initialMinutes: Int = 0,
    timeValue: String = "",
    onTimeSelect: (TimePickerState) -> Unit = {},
) {
    val showTimePicker = remember {
        mutableStateOf(false)
    }
    TextField(
        modifier = Modifier
            .clickable {
                showTimePicker.value = true
            }
            .width(100.dp),
        textStyle = TextStyle.Default.copy(fontSize = 20.sp),
        enabled = false,
        value = timeValue,
        onValueChange = { }
    )
    if (showTimePicker.value) {
        CommonTimePickerDialog(
            // OKを押さずに閉じた場合は初期値に戻る方が自然だと思うのでここで初期化しています。
            timePickerState = remember {
                TimePickerState(
                    initialHour = initialHour,
                    initialMinute = initialMinutes,
                    is24Hour = true
                )
            },
            onConfirm = {
                onTimeSelect(it)
                showTimePicker.value = false
            },
            onDismiss = {
                showTimePicker.value = false
            }
        )
    }
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?