Pemilih tanggal

Alat pilih tanggal memungkinkan pengguna memilih tanggal, rentang tanggal, atau keduanya. Mereka menggunakan dialog kalender atau input teks untuk memungkinkan pengguna memilih tanggal.

Jenis

Ada tiga jenis pemilih tanggal:

  • Tersemat: Muncul sebaris dalam tata letak. Ini cocok untuk rapat tata letak di mana dialog khusus mungkin terasa mengganggu.
  • Modal: Muncul sebagai dialog yang menempatkan konten aplikasi. Hal ini memberikan fokus yang jelas pada pemilihan tanggal.
  • Input modal: Menggabungkan kolom teks dengan pemilih tanggal modal.

Anda dapat menerapkan pemilih tanggal ini di aplikasi Anda menggunakan composable:

  • DatePicker: Composable umum untuk pemilih tanggal. Container yang Anda menentukan apakah itu dipasang ke dok atau dibuat modelnya.
  • DatePickerDialog: Penampung untuk tanggal input modal dan modal pemilih.
  • DateRangePicker: Untuk pemilih tanggal apa pun tempat pengguna dapat memilih rentang dengan tanggal mulai dan akhir.

Status

Parameter kunci yang sama-sama dimiliki oleh berbagai composable pemilih tanggal adalah state, yang menggunakan DatePickerState atau DateRangePickerState. Properti mereka mengambil informasi tentang pilihan pengguna menggunakan pemilih tanggal, seperti tanggal yang dipilih saat ini.

Untuk informasi selengkapnya tentang cara memanfaatkan tanggal yang dipilih, lihat dokumen bagian tanggal yang dipilih.

Pemilih tanggal yang dipasang ke dok

Pada contoh berikut, ada kolom teks yang meminta pengguna untuk memasukkan tanggal lahir mereka. Ketika mereka mengeklik ikon kalender di bidang, hal itu akan membuka pemilih tanggal dipasang ke dok di bawah kolom input.

@Composable
fun DatePickerDocked() {
    var showDatePicker by remember { mutableStateOf(false) }
    val datePickerState = rememberDatePickerState()
    val selectedDate = datePickerState.selectedDateMillis?.let {
        convertMillisToDate(it)
    } ?: ""

    Box(
        modifier = Modifier.fillMaxWidth()
    ) {
        OutlinedTextField(
            value = selectedDate,
            onValueChange = { },
            label = { Text("DOB") },
            readOnly = true,
            trailingIcon = {
                IconButton(onClick = { showDatePicker = !showDatePicker }) {
                    Icon(
                        imageVector = Icons.Default.DateRange,
                        contentDescription = "Select date"
                    )
                }
            },
            modifier = Modifier
                .fillMaxWidth()
                .height(64.dp)
        )

        if (showDatePicker) {
            Popup(
                onDismissRequest = { showDatePicker = false },
                alignment = Alignment.TopStart
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .offset(y = 64.dp)
                        .shadow(elevation = 4.dp)
                        .background(MaterialTheme.colorScheme.surface)
                        .padding(16.dp)
                ) {
                    DatePicker(
                        state = datePickerState,
                        showModeToggle = false
                    )
                }
            }
        }
    }
}

fun convertMillisToDate(millis: Long): String {
    val formatter = SimpleDateFormat("MM/dd/yyyy", Locale.getDefault())
    return formatter.format(Date(millis))
}

Poin penting tentang kode

  • Pemilih tanggal akan muncul saat pengguna mengklik IconButton.
    • Tombol ikon berfungsi sebagai argumen untuk OutlinedTextField Parameter trailingIcon.
    • Variabel status showDatePicker mengontrol visibilitas pemilih tanggal terpasang ke dok.
  • Penampung pemilih tanggal adalah composable Popup, yang menempatkan konten tanpa mempengaruhi tata letak elemen lain.
  • selectedDate menangkap nilai tanggal yang dipilih dari objek DatePickerState dan memformatnya menggunakan convertMillisToDate fungsi tersebut.
  • Tanggal yang dipilih akan muncul di kolom teks.
  • Pemilih tanggal yang dipasang ke dok diposisikan di bawah kolom teks menggunakan offset pengubah.
  • Box digunakan sebagai penampung root untuk memungkinkan pelapisan teks yang tepat dan pemilih tanggal.

Hasil

Setelah mengklik ikon kalender, implementasi ini akan muncul sebagai berikut:

Contoh pemilih tanggal yang dipasang ke dok.
Gambar 1. Pemilih tanggal yang dipasang ke dok.

Pemilih tanggal modal menampilkan dialog yang mengambang di atas layar. Untuk menerapkan buat DatePickerDialog, lalu teruskan DatePicker.

@Composable
fun DatePickerModal(
    onDateSelected: (Long?) -> Unit,
    onDismiss: () -> Unit
) {
    val datePickerState = rememberDatePickerState()

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                onDateSelected(datePickerState.selectedDateMillis)
                onDismiss()
            }) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DatePicker(state = datePickerState)
    }
}

  • Fungsi composable DatePickerModal menampilkan pemilih tanggal modal.
  • Ekspresi lambda onDateSelected dijalankan saat pengguna memilih tanggal.
    • Composable ini mengekspos tanggal yang dipilih ke composable induk.
  • Ekspresi lambda onDismiss dijalankan saat pengguna menutup dialog.

Hasil

Implementasi ini muncul sebagai berikut:

Contoh pemilih tanggal modal.
Gambar 2. Pemilih tanggal modal.

Input pemilih tanggal modal

Pemilih tanggal modal dengan input menampilkan dialog yang mengambang di atas layar dan memungkinkan pengguna untuk memasukkan tanggal.

@Composable
fun DatePickerModalInput(
    onDateSelected: (Long?) -> Unit,
    onDismiss: () -> Unit
) {
    val datePickerState = rememberDatePickerState(initialDisplayMode = DisplayMode.Input)

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                onDateSelected(datePickerState.selectedDateMillis)
                onDismiss()
            }) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DatePicker(state = datePickerState)
    }
}

Ini sangat sama dengan contoh pemilih tanggal modal. Utama perbedaannya adalah sebagai berikut:

  • Parameter initialDisplayMode menetapkan mode tampilan awal ke DisplayMode.Input.
Pemilih tanggal modal dengan input.
Gambar 3. Pemilih tanggal modal dengan input.

Pemilih tanggal dengan rentang

Anda dapat membuat pemilih tanggal yang memungkinkan pengguna memilih rentang antara tanggal dan tanggal akhir. Untuk melakukannya, gunakan DateRangePicker.

Penggunaan DateRangePicker pada dasarnya sama dengan DatePicker. Anda dapat Anda dapat menggunakannya untuk pemilih yang dipasang ke dok sebagai turunan dari PopUp, atau Anda dapat menggunakannya sebagai pemilih modal dan teruskan ke DatePickerDialog. Perbedaan utamanya adalah bahwa Anda menggunakan DateRangePickerState, bukan DatePickerState.

Cuplikan berikut menunjukkan cara membuat pemilih tanggal modal dengan rentang:

@Composable
fun DateRangePickerModal(
    onDateRangeSelected: (Pair<Long?, Long?>) -> Unit,
    onDismiss: () -> Unit
) {
    val dateRangePickerState = rememberDateRangePickerState()

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(
                onClick = {
                    onDateRangeSelected(
                        Pair(
                            dateRangePickerState.selectedStartDateMillis,
                            dateRangePickerState.selectedEndDateMillis
                        )
                    )
                    onDismiss()
                }
            ) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DateRangePicker(
            state = dateRangePickerState,
            title = {
                Text(
                    text = "Select date range"
                )
            },
            showModeToggle = false,
            modifier = Modifier
                .fillMaxWidth()
                .height(500.dp)
                .padding(16.dp)
        )
    }
}

Poin penting tentang kode

  • Parameter onDateRangeSelected adalah callback yang menerima Pair<Long?, Long?> yang menunjukkan tanggal mulai dan akhir yang dipilih. Ini memberi composable induk akses ke rentang yang dipilih.
  • rememberDateRangePickerState() membuat status untuk rentang tanggal pemilih.
  • DatePickerDialog membuat container dialog modal.
  • Di pengendali onClick tombol konfirmasi, onDateRangeSelected akan diteruskan rentang yang dipilih ke composable induk.
  • Composable DateRangePicker berfungsi sebagai konten dialog.

Hasil

Implementasi ini muncul sebagai berikut:

Contoh pemilih tanggal rentang modal.
Gambar 4. Pemilih tanggal modal dengan rentang yang dipilih.

Gunakan tanggal yang dipilih

Untuk mengambil tanggal yang dipilih, lacak di composable induk sebagai Long dan teruskan nilai ke DatePicker di onDateSelected. Cuplikan berikut akan menunjukkan hal ini, meskipun Anda dapat melihat implementasi lengkapnya aplikasi cuplikan.

// ...
    var selectedDate by remember { mutableStateOf<Long?>(null) }
// ...
        if (selectedDate != null) {
            val date = Date(selectedDate!!)
            val formattedDate = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()).format(date)
            Text("Selected date: $formattedDate")
        } else {
            Text("No date selected")
        }
// ...
        DatePickerModal(
            onDateSelected = {
                selectedDate = it
                showModal = false
            },
            onDismiss = { showModal = false }
        )
    }
// ...

Pada dasarnya, hal yang sama berlaku untuk pemilih tanggal rentang, meskipun Anda harus gunakan Pair<Long?, Long?> atau class data untuk mengambil nilai awal dan akhir.

Lihat juga