はじめに
JetpackCompose個人開発でDatePickerやTimePickerを使った時に迷ったりつまづいたりした部分をまとめます。
DatePicker, TimePickerとは
MaterialDesign3で提供されている、日時を取得するUIコンポーネントです。
DatePicker
TimePicker
DatePicker
実装方法
build.gradleにimplementation("androidx.compose.material3:material3:$m3-version"
を追加して、Composable関数に@OptIn(ExperimentalMaterial3Api::class)
などのアノテーションを使用することで組み込むことができます。
サンプルコード
先ほどのリンク先にあるDataPickerのサンプルコードです。
//... import
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
// Pre-select a date for January 4, 2020
val datePickerState = rememberDatePickerState(initialSelectedDateMillis = 1578096000000)
DatePicker(state = datePickerState, modifier = Modifier.padding(16.dp))
Text("Selected date timestamp: ${datePickerState.selectedDateMillis ?: "no selection"}")
}
datePickerの実装にはDatePickerState型の引数が必要であることがわかります。また、datePickerStateの変数宣言では初期値を定義されており、どのような形でデータが保持されているのかもわかります。その下のTextから、値はdatePickerState.selectedDateMillis
に保持されているということもわかりました。
DatePickerのデーターを保存する
データを取得したら保持したいですよね。実は、導入する部分についてはまとめられていましたが、そこからどう値を保持すればいいのか分からず、kotloinの実装に慣れていない私は苦戦しました。
結論、DatePickerに引数で渡したdatePickerState
に対して変更が行われるため、引数のdataPickerStateを参照すればいいです。変更が行われたかどうかについてはDatePickerDialog
と組み合わせると簡単に管理できます。
上記のコード同様、DatePickerのドキュメントにあるサンプルコードの抜粋です。
// ...
DatePickerDialog(
// Dialogの外側を触ったときの挙動
onDismissRequest = {
openDialog.value = false
},
// OKボタン
confirmButton = {
TextButton(
// OKボタンを押したときの挙動
onClick = {
openDialog.value = false
// ...
},
enabled = confirmEnabled.value
) {
Text("OK")
}
},
// Cancelボタン
dismissButton = {
TextButton(
onClick = {
// Cancelボタンを押したときの挙動
openDialog.value = false
}
) {
Text("Cancel")
}
}
) {
DatePicker(state = datePickerState)
}
DatePickerDialog
の引数に、各ボタンを押したとき実行する処理を入れられるので、データ保持などをしたいのであればOKの時のonClickの処理でデータ保持の関数を呼び出してあげるとうまくいきそうですね。保持するデータは先ほど確認した通り、datePickerState.selectedDateMillis
で取り出せるのでこちらを渡せばうまくいくはずです。
TimePicker
サンプルコード
TimePickerのサンプルコードの抜粋です。
// ...
TimePickerDialog(
onCancel = { showTimePicker = false },
onConfirm = {
val cal = Calendar.getInstance()
cal.set(Calendar.HOUR_OF_DAY, state.hour)
cal.set(Calendar.MINUTE, state.minute)
cal.isLenient = false
snackScope.launch {
snackState.showSnackbar("Entered time: ${formatter.format(cal.time)}")
}
showTimePicker = false
},
) {
TimePicker(state = state)
}
TimePickerをDatePicker同様に実装しようとしたら、DatePickerDialogのようなUIコンポーネントが提供されていないことがわかりました。調べて該当するサンプルコードを見つけることができました。
このリンクから引用して実装すると、TimePickerのドキュメントにある画像と同様のUIコンポーネントを実装できました。
TimePickerのデーターを保存する
DatePicker同様、TimePickerにrememberTimePickerState()
を使用して定義した値state: TimePickerState
を引数で渡して、変更がこの引数に対して行われます。取り出す際はstate.hour
やstate.minute
とすれば値を返してくれます。