日期选择器

通过日期选择器,用户可以选择日期和/或日期范围。他们使用 日历对话框或文本输入,以便用户选择日期。

类型

日期选择器有三种类型:

  • 停靠:内嵌在布局中显示。它适用于 在布局中,专门的对话框可能会让人感觉有干扰。
  • 模态:显示为叠加在应用内容的对话框。这提供了一个 明确选择日期。
  • 模态输入:将文本字段与模态日期选择器结合起来。

您可以使用以下代码在应用中实现这些日期选择器 可组合项:

  • 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 lambda 表达式会在用户选择 日期。
    • 它会将所选日期公开给父级可组合项。
  • onDismiss lambda 表达式会在用户关闭 对话框。

结果

此实现如下所示:

模态日期选择器示例。
图 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?> 或数据类来捕获起始值和结束值。

另请参阅