日期挑選器

日期挑選器可讓使用者選取日期和/或日期範圍。他們使用 日曆對話方塊或文字輸入欄位,可讓使用者選取日期。

類型

日期挑選器分為三種:

  • 固定:顯示在版面配置中。適合使用密集 讓專用對話方塊感覺受到干擾。
  • 強制回應:顯示為與應用程式內容重疊的對話方塊。因此,您可以 取消焦點。
  • 強制回應輸入:將文字欄位與強制回應日期挑選器合併。

您可以透過下列方式,在應用程式中實作這些日期挑選器 可組合函式:

  • DatePicker:日期挑選器的一般可組合項。您執行的容器 是否要插入座架或模型。
  • DatePickerDialog:互動視窗和強制回應輸入日期的容器 選擇工具
  • DateRangePicker:任何可供使用者選取 日期範圍。
,瞭解如何調查及移除這項存取權。

狀態

不同日期挑選器可組合項的共通點,就是 state,可接受 DatePickerStateDateRangePickerState 物件。他們的資源會擷取 使用日期挑選器 (例如目前選取的日期) 取得使用者的選項。

如要進一步瞭解如何運用所選日期,請參閱使用 選取的日期區段

固定日期挑選器

在以下範例中,有一個文字欄位會提示使用者輸入內容 他們的出生日期。當使用者按一下欄位中的日曆圖示時, 將日期挑選器置於輸入欄位下方。

@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))
}

程式碼相關重點

  • 使用者按一下 IconButton 時,會顯示日期挑選器。
    • 圖示按鈕可做為 OutlinedTextFieldtrailingIcon 參數。
    • showDatePicker 狀態變數用來控制 已停駐的日期挑選器。
  • 日期挑選器的容器是 Popup 可組合函式,會疊加顯示 而不影響其他元素的版面配置。
  • selectedDate 會從 DatePickerState 物件,並使用 convertMillisToDate 將其格式化 函式。
  • 所選日期會顯示在文字欄位中。
  • 固定日期挑選器位於文字欄位下方,使用 offset 修飾符
  • 使用 Box 做為根容器,以便適當地分層文字 和日期挑選器。

結果

按一下日曆圖示後,這個實作方式會如下所示:

固定日期挑選器範例。
圖 1. 固定的日期挑選器。

強制回應日期挑選器會顯示浮動於畫面上的對話方塊。如要在 請建立 DatePickerDialog,並傳遞 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)
    }
}

  • DatePickerModal 可組合函式會顯示強制回應日期挑選器,
  • 當使用者選取onDateSelected 日期。
    • 這會向父項可組合項公開選取的日期。
  • 當使用者關閉onDismiss 對話方塊

結果

實作內容如下所示:

強制回應日期挑選器範例。
圖 2. 強制回應日期挑選器。

輸入強制回應日期挑選器

包含輸入內容的強制回應日期挑選器會顯示對話方塊,該對話方塊會浮動顯示在畫面中, 可讓使用者輸入日期

@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)
    }
}

這與強制回應日期挑選器範例非常相同。主要 不同之處如下:

  • initialDisplayMode 參數會將初始顯示模式設為 DisplayMode.Input
,瞭解如何調查及移除這項存取權。
含有輸入內容的強制回應日期挑選器。
圖 3.包含輸入內容的強制回應日期挑選器。

包含範圍的日期挑選器

你可以建立日期挑選器,讓使用者選取兩個起始值之間的範圍 和結束日期方法是使用 DateRangePicker

使用 DateRangePicker 基本上與 DatePicker 相同。你可以 將其用於固定挑選器做為 PopUp 的子項,或者將其做為 強制回應挑選器,並傳遞至 DatePickerDialog。主要差異在於 您使用 DateRangePickerState 而不是 DatePickerState

下列程式碼片段示範如何使用 範圍:

@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)
        )
    }
}

程式碼相關重點

  • onDateRangeSelected 參數是一個回呼,用來接收 Pair<Long?, Long?>,代表所選開始和結束日期。這個 會授予父項可組合函式對所選範圍的存取權。
  • rememberDateRangePickerState() 會建立日期範圍內的狀態 。
  • DatePickerDialog 會建立強制回應對話方塊容器。
  • 在確認按鈕的 onClick 處理常式中,onDateRangeSelected 會向上傳遞 將所選範圍複製到父項可組合函式
  • DateRangePicker 可組合函式會當做對話方塊內容。

結果

實作內容如下所示:

強制回應範圍日期挑選器範例。
圖 4. 包含所選範圍的強制回應日期挑選器。

使用所選日期

如要擷取所選日期,請在父項可組合函式中以 Long 進行追蹤,並 將值傳遞至 onDateSelected 中的 DatePicker。下列程式碼片段 但您可以在官方課程 程式碼片段應用程式

// ...
    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 }
        )
    }
// ...

範圍日期挑選器基本上同樣適用,但您必須 使用 Pair<Long?, Long?> 或資料類別擷取開始和結束值。

另請參閱