Hộp thoại cho bộ chọn giờ

Bộ chọn thời gian thường xuất hiện trong các hộp thoại. Bạn có thể sử dụng một cách triển khai tương đối chung chung và tối thiểu cho hộp thoại, hoặc bạn có thể triển khai một hộp thoại tuỳ chỉnh linh hoạt hơn.

Để biết thêm thông tin về hộp thoại nói chung, bao gồm cả cách sử dụng trạng thái bộ chọn thời gian, hãy xem Hướng dẫn về bộ chọn thời gian.

Ví dụ cơ bản

Cách đơn giản nhất để tạo hộp thoại cho bộ chọn thời gian là tạo một thành phần kết hợp triển khai AlertDialog. Đoạn mã sau đây cung cấp ví dụ về một hộp thoại tương đối tối giản bằng cách sử dụng phương pháp này:

@Composable
fun DialWithDialogExample(
    onConfirm: (TimePickerState) -> Unit,
    onDismiss: () -> Unit,
) {
    val currentTime = Calendar.getInstance()

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

    TimePickerDialog(
        onDismiss = { onDismiss() },
        onConfirm = { onConfirm(timePickerState) }
    ) {
        TimePicker(
            state = timePickerState,
        )
    }
}

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

Lưu ý những điểm chính trong đoạn mã này:

  1. Thành phần kết hợp DialWithDialogExample bao bọc TimePicker trong một hộp thoại.
  2. TimePickerDialog là một thành phần kết hợp tuỳ chỉnh tạo ra một AlertDialog với các tham số sau:
    • onDismiss: Một hàm được gọi khi người dùng đóng hộp thoại (thông qua nút đóng hoặc thao tác quay lại).
    • onConfirm: Một hàm được gọi khi người dùng nhấp vào nút "OK".
    • content: Một thành phần kết hợp hiển thị bộ chọn giờ trong hộp thoại.
  3. AlertDialog bao gồm:
    • Một nút đóng có nhãn "Đóng".
    • Một nút xác nhận có nhãn "OK".
    • Nội dung của bộ chọn thời gian được truyền dưới dạng tham số text.
  4. DialWithDialogExample khởi tạo TimePickerState bằng thời gian hiện tại và truyền nó vào cả hàm TimePickeronConfirm.
Bộ chọn thời gian trong AlertDialog triển khai tiêu đề, chế độ bật/tắt, cũng như các nút đóng và xác nhận.
Hình 1. Bộ chọn giờ trong AlertDialog.

Ví dụ nâng cao

Đoạn mã này minh hoạ một cách triển khai nâng cao của hộp thoại bộ chọn thời gian có thể tuỳ chỉnh trong Jetpack Compose.

@Composable
fun AdvancedTimePickerExample(
    onConfirm: (TimePickerState) -> Unit,
    onDismiss: () -> Unit,
) {

    val currentTime = Calendar.getInstance()

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

    /** Determines whether the time picker is dial or input */
    var showDial by remember { mutableStateOf(true) }

    /** The icon used for the icon button that switches from dial to input */
    val toggleIcon = if (showDial) {
        Icons.Filled.EditCalendar
    } else {
        Icons.Filled.AccessTime
    }

    AdvancedTimePickerDialog(
        onDismiss = { onDismiss() },
        onConfirm = { onConfirm(timePickerState) },
        toggle = {
            IconButton(onClick = { showDial = !showDial }) {
                Icon(
                    imageVector = toggleIcon,
                    contentDescription = "Time picker type toggle",
                )
            }
        },
    ) {
        if (showDial) {
            TimePicker(
                state = timePickerState,
            )
        } else {
            TimeInput(
                state = timePickerState,
            )
        }
    }
}

@Composable
fun AdvancedTimePickerDialog(
    title: String = "Select Time",
    onDismiss: () -> Unit,
    onConfirm: () -> Unit,
    toggle: @Composable () -> Unit = {},
    content: @Composable () -> Unit,
) {
    Dialog(
        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 = title,
                    style = MaterialTheme.typography.labelMedium
                )
                content()
                Row(
                    modifier = Modifier
                        .height(40.dp)
                        .fillMaxWidth()
                ) {
                    toggle()
                    Spacer(modifier = Modifier.weight(1f))
                    TextButton(onClick = onDismiss) { Text("Cancel") }
                    TextButton(onClick = onConfirm) { Text("OK") }
                }
            }
        }
    }
}

Lưu ý những điểm chính trong đoạn mã này:

  1. Thành phần kết hợp AdvancedTimePickerExample tạo một hộp thoại bộ chọn thời gian có thể tuỳ chỉnh.
  2. Thành phần này sử dụng thành phần kết hợp Dialog để linh hoạt hơn so với AlertDialog.
  3. Hộp thoại này có tiêu đề có thể tuỳ chỉnh và một nút bật/tắt để chuyển đổi giữa chế độ quay số và chế độ nhập.
  4. Surface áp dụng hình dạng và độ cao cho hộp thoại, với IntrinsicSize.Min cho cả chiều rộng và chiều cao.
  5. Bố cục ColumnRow cung cấp các thành phần cấu trúc của hộp thoại.
  6. Ví dụ này theo dõi chế độ của bộ chọn bằng cách sử dụng showDial.
    • IconButton sẽ chuyển đổi giữa các chế độ và cập nhật biểu tượng cho phù hợp.
    • Nội dung hộp thoại chuyển đổi giữa TimePickerTimeInput dựa trên trạng thái showDial.

Việc triển khai nâng cao này cung cấp một hộp thoại bộ chọn thời gian có khả năng tuỳ chỉnh cao và có thể dùng lại, đồng thời có thể thích ứng với nhiều trường hợp sử dụng trong ứng dụng của bạn.

Phương thức triển khai có dạng như sau:

Bộ chọn thời gian trong một hộp thoại tuỳ chỉnh triển khai tiêu đề, nút bật/tắt chế độ, cũng như các nút đóng và xác nhận.
Hình 2. Bộ chọn giờ trong hộp thoại tuỳ chỉnh.

Tài nguyên khác