Выбор даты

Средства выбора дат позволяют пользователям выбирать дату, диапазон дат или и то, и другое. Они используют диалоговое окно календаря или ввод текста, чтобы пользователи могли выбирать даты.

Типы

Существует три типа выбора даты:

  • Закреплено : отображается внутри макета. Он подходит для компактных макетов, где выделенный диалог может показаться навязчивым.
  • Модальное окно : отображается в виде диалогового окна, накладывающего содержимое приложения. Это обеспечивает четкую фокусировку на выборе даты.
  • Модальный ввод : объединяет текстовое поле с модальным выбором даты.

Вы можете реализовать эти средства выбора дат в своем приложении, используя следующие составные элементы:

  • DatePicker : общий вариант для выбора даты. Используемый вами контейнер определяет, будет ли он закреплен или модель.
  • DatePickerDialog : контейнер для модальных и модальных средств выбора даты ввода.
  • DateRangePicker : для любого средства выбора даты, где пользователь может выбрать диапазон с датой начала и окончания.

Состояние

Ключевым параметром, который является общим для различных составных элементов выбора даты, является state , который принимает объект DatePickerState или DateRangePickerState . Их свойства собирают информацию о выборе пользователя с помощью средства выбора даты, например текущую выбранную дату.

Дополнительную информацию о том, как использовать выбранную дату, можно найти в разделе «Использовать выбранную дату» .

Закрепленный выбор даты

В следующем примере есть текстовое поле, предлагающее пользователю ввести дату рождения. Когда они щелкают значок календаря в поле, под полем ввода открывается закрепленное средство выбора даты.

@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 .
    • Кнопка со значком служит аргументом для параметра trailingIcon OutlinedTextField .
    • Переменная состояния 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 и передайте значение DatePicker в onDateSelected . Следующий фрагмент демонстрирует это, хотя полную реализацию можно увидеть в официальном приложении фрагментов .

// ...
   
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?> или класс данных для захвата начального и конечного значений.

См. также

,

Средства выбора дат позволяют пользователям выбирать дату, диапазон дат или и то, и другое. Они используют диалоговое окно календаря или ввод текста, чтобы пользователи могли выбирать даты.

Типы

Существует три типа выбора даты:

  • Закреплено : отображается внутри макета. Он подходит для компактных макетов, где выделенный диалог может показаться навязчивым.
  • Модальное окно : отображается в виде диалогового окна, накладывающего содержимое приложения. Это обеспечивает четкую фокусировку на выборе даты.
  • Модальный ввод : объединяет текстовое поле с модальным выбором даты.

Вы можете реализовать эти средства выбора дат в своем приложении, используя следующие составные элементы:

  • DatePicker : общий вариант для выбора даты. Используемый вами контейнер определяет, будет ли он закреплен или модель.
  • DatePickerDialog : контейнер для модальных и модальных средств выбора даты ввода.
  • DateRangePicker : для любого средства выбора даты, где пользователь может выбрать диапазон с датой начала и окончания.

Состояние

Ключевым параметром, который является общим для различных составных элементов выбора даты, является state , который принимает объект DatePickerState или DateRangePickerState . Их свойства собирают информацию о выборе пользователя с помощью средства выбора даты, например текущую выбранную дату.

Дополнительную информацию о том, как использовать выбранную дату, можно найти в разделе «Использовать выбранную дату» .

Закрепленный выбор даты

В следующем примере есть текстовое поле, предлагающее пользователю ввести дату рождения. Когда они щелкают значок календаря в поле, под полем ввода открывается закрепленное средство выбора даты.

@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 .
    • Кнопка со значком служит аргументом для параметра trailingIcon OutlinedTextField .
    • Переменная состояния 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 и передайте значение DatePicker в onDateSelected . Следующий фрагмент демонстрирует это, хотя полную реализацию можно увидеть в официальном приложении фрагментов .

// ...
   
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?> или класс данных для захвата начального и конечного значений.

См. также

,

Средства выбора дат позволяют пользователям выбирать дату, диапазон дат или и то, и другое. Они используют диалоговое окно календаря или ввод текста, чтобы пользователи могли выбирать даты.

Типы

Существует три типа выбора даты:

  • Закреплено : отображается внутри макета. Он подходит для компактных макетов, где выделенный диалог может показаться навязчивым.
  • Модальное окно : отображается в виде диалогового окна, накладывающего содержимое приложения. Это обеспечивает четкую фокусировку на выборе даты.
  • Модальный ввод : объединяет текстовое поле с модальным выбором даты.

Вы можете реализовать эти средства выбора дат в своем приложении, используя следующие составные элементы:

  • DatePicker : общий вариант для выбора даты. Используемый вами контейнер определяет, будет ли он закреплен или модель.
  • DatePickerDialog : контейнер для модальных и модальных средств выбора даты ввода.
  • DateRangePicker : для любого средства выбора даты, где пользователь может выбрать диапазон с датой начала и окончания.

Состояние

Ключевым параметром, который является общим для различных составных элементов выбора даты, является state , который принимает объект DatePickerState или DateRangePickerState . Их свойства собирают информацию о выборе пользователя с помощью средства выбора даты, например текущую выбранную дату.

Дополнительную информацию о том, как использовать выбранную дату, можно найти в разделе «Использовать выбранную дату» .

Закрепленный выбор даты

В следующем примере есть текстовое поле, предлагающее пользователю ввести дату рождения. Когда они щелкают значок календаря в поле, под полем ввода открывается закрепленное средство выбора даты.

@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 .
    • Кнопка со значком служит аргументом для параметра trailingIcon OutlinedTextField .
    • Переменная состояния 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 и передайте значение DatePicker в onDateSelected . Следующий фрагмент демонстрирует это, хотя полную реализацию можно увидеть в официальном приложении фрагментов .

// ...
   
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?> или класс данных для захвата начального и конечного значений.

См. также

,

Средства выбора дат позволяют пользователям выбирать дату, диапазон дат или и то, и другое. Они используют диалоговое окно календаря или ввод текста, чтобы пользователи могли выбирать даты.

Типы

Существует три типа выбора даты:

  • Закреплено : отображается внутри макета. Он подходит для компактных макетов, где выделенный диалог может показаться навязчивым.
  • Модальное окно : отображается в виде диалогового окна, накладывающего содержимое приложения. Это обеспечивает четкую фокусировку на выборе даты.
  • Модальный ввод : объединяет текстовое поле с модальным выбором даты.

Вы можете реализовать эти средства выбора дат в своем приложении, используя следующие составные элементы:

  • DatePicker : общий вариант для выбора даты. Используемый вами контейнер определяет, будет ли он закреплен или модель.
  • DatePickerDialog : контейнер для модальных и модальных средств выбора даты ввода.
  • DateRangePicker : для любого средства выбора даты, где пользователь может выбрать диапазон с датой начала и окончания.

Состояние

Ключевым параметром, который является общим для различных составных элементов выбора даты, является state , который принимает объект DatePickerState или DateRangePickerState . Их свойства собирают информацию о выборе пользователя с помощью средства выбора даты, например текущую выбранную дату.

Дополнительную информацию о том, как использовать выбранную дату, можно найти в разделе «Использовать выбранную дату» .

Закрепленный выбор даты

В следующем примере есть текстовое поле, предлагающее пользователю ввести дату рождения. Когда они щелкают значок календаря в поле, под полем ввода открывается закрепленное средство выбора даты.

@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 .
    • Кнопка со значком служит аргументом для параметра trailingIcon OutlinedTextField .
    • Переменная состояния 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 и передайте значение DatePicker в onDateSelected . Следующий фрагмент демонстрирует это, хотя полную реализацию можно увидеть в официальном приложении фрагментов .

// ...
   
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?> или класс данных для захвата начального и конечного значений.

См. также