I've a dialog where I show time picker. If the use...
# compose-android
a
I've a dialog where I show time picker. If the user selects a time in the past, I show a snackbar. The snackbar is shown in the background (darkened) and not on the foreground (white background with black text). Does anyone know how to make the snackbar show in the foreground? Overlaying the dialog?
a
this happens because dialogs dim the background and are drawn on a separate window. you would have to show the snackbar on the same window as the Dialog – ie adding the snackbar on the dialog's content. not sure if it's worth the trouble though. could u modify the picker disabling the option to move forward when the time is invalid?
plus1 1
a
I see. Sounds complex/complicated. I'm already doing sanity checks and prevent the action going forward if time is invalid. Though, having the warning show in the background isn't very user friendly. The user has to pay close attention to see it.
c
Also I would say UX wise it’s not a good idea to react to user input “errors” with a snackbar on top of the dialog. If the user should not be able to select dates in the past, restrict the input in the picker.
plus1 2
ah, there is no API in the
TimePickerState
to restrict the input, thats only available in the
DatePickerState
🤔
you can use a
snapshotFlow
to indicate “errors”
Copy code
@Composable
fun DailExample(
    onConfirm: (TimePickerState) -> Unit,
    onDismiss: () -> Unit,
    modifier: Modifier = Modifier,
) {
    val currentTime = Calendar.getInstance()

    val timePickerState =
        rememberTimePickerState(
            initialHour = currentTime[Calendar.HOUR_OF_DAY],
            initialMinute = currentTime[Calendar.MINUTE],
            is24Hour = true,
        )

    var hasError by remember {
        mutableStateOf(false)
    }

    LaunchedEffect(timePickerState) {
        snapshotFlow { timePickerState.hour }
            .combine(snapshotFlow { timePickerState.minute }) { _, _ -> timePickerState }
            .collect { state ->
                Log.v("TimePickerDialog", "${state.hour}:${state.minute}")
                hasError = state.hour > 10
            }
    }

    TimePickerDialog(
        modifier = modifier,
        onDismiss = { onDismiss() },
        onConfirm = { onConfirm(timePickerState) },
    ) {
        val errorText =
            if (hasError) {
                "Error"
            } else {
                ""
            }
        Column {
            TimePicker(
                state = timePickerState,
                colors =
                    TimePickerDefaults.colors(
                        selectorColor = if (hasError) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary,
                    ),
            )
            Text(errorText)
        }
    }
}

@Composable
fun TimePickerDialog(
    modifier: Modifier,
    onDismiss: () -> Unit,
    onConfirm: () -> Unit,
    content: @Composable () -> Unit,
) {
    AlertDialog(
        onDismissRequest = onDismiss,
        dismissButton = {
            TextButton(onClick = { onDismiss() }) {
                Text("Dismiss")
            }
        },
        confirmButton = {
            TextButton(onClick = { onConfirm() }) {
                Text("OK")
            }
        },
        text = { content() },
    )
}
👍🏻 1