🍈
Jetpack ComposeでTimePickerをキャンセル可能にする
androidx.compose.material3
のTimePickerをキャンセル可能にしようという趣旨の記事です。
The purpose of this article is to make TimePicker cancelable.
timePickerStateは、時計上で時間を選択したらその要素である
timePickerState.hour
等が更新されてしまうので、このままだと
『OKを押すと時間の変更を確定』
『Cancelを押すと時間の変更を元に戻す』
というような動作ができません。そこで、次の拡張関数を作ります。
@OptIn(ExperimentalMaterial3Api::class)
class CustomTimePickerState (
var timeState: TimePickerState,
var pendingTimeState: TimePickerState
) {
companion object {
/**
* The default [Saver] implementation for [CustomTimePickerState].
*/
fun Saver(): Saver<CustomTimePickerState, *> = Saver(
save = {
listOf(
it.timeState.hour,
it.timeState.minute,
it.timeState.is24hour
)
},
restore = { value ->
CustomTimePickerState(
TimePickerState(
initialHour = value[0] as Int,
initialMinute = value[1] as Int,
is24Hour = value[2] as Boolean
),
TimePickerState(
initialHour = value[0] as Int,
initialMinute = value[1] as Int,
is24Hour = value[2] as Boolean
)
)
}
)
}
}
@Composable
@ExperimentalMaterial3Api
fun rememberCustomTimePickerState(
initialHour: Int = 0,
initialMinute: Int = 0,
is24Hour: Boolean = DateFormat.is24HourFormat(LocalContext.current),
): CustomTimePickerState {
return rememberSaveable(
saver = CustomTimePickerState.Saver()
) {
CustomTimePickerState(
TimePickerState(
initialHour = initialHour,
initialMinute = initialMinute,
is24Hour = is24Hour,
),
TimePickerState(
initialHour = initialHour,
initialMinute = initialMinute,
is24Hour = is24Hour,
)
)
}
}
stateに新規にpendingTimeStateを追加しています。
これを次のように実装します。
var showTimePickerDialog by remember { mutableStateOf(false) }
val customState = rememberCustomTimePickerState()
if (showTimePickerDialog) {
TimePickerDialog(
},
onConfirm = {
showTimePickerLeftDialog = false
timePickerState.pendingTimeState = TimePickerState(
timePickerState.timeState.hour,
timePickerState.timeState.minute,
timePickerState.timeState.is24hour
)
},
onDismiss = {
showDatePickerDialog = false
timePickerState.timeState = TimePickerState(
timePickerState.pendingTimeState.hour,
timePickerState.pendingTimeState.minute,
timePickerState.pendingTimeState.is24hour
)
}
) {
DatePicker(
TimePicker(state = timePickerState.pendingTimeState)
)
}
}
Discussion