Я использую эту библиотеку компоновки для выбора даты: https://github.com/maxkeppeler/sheets-compose-dialogs
Composable принимает только запрещенные даты следующим образом:
val disabledDates = listOf(
LocalDate.now().plusDays(3),
LocalDate.now().plusDays(5),
LocalDate.now().plusDays(7),
)
CalendarView(
useCaseState = rememberUseCaseState(),
config = CalendarConfig(
style = CalendarStyle.MONTH,
disabledDates = disabledDates,
boundary = LocalDate.now()..LocalDate.now().plusYears(10),
),
selection = CalendarSelection.Date { newDate ->
selectedDate.value = newDate
},
)
Проблема в том, что вместо этого мне нужно передать только несколько разрешенных дат. Как я могу этого добиться? Есть ли способ преобразовать разрешенные даты в список запрещенных дат или что-то в этом роде?
Поскольку эта композиция позволяет отключать только определенные дни из заданных boundary, невозможно предоставить список всех дат за вычетом тех, которые вы хотите разрешить.
Предположим, что отключенные даты из вашего примера на самом деле являются разрешенными датами. Затем вам нужно будет удалить эти даты из диапазона, который должен отображать календарь (boundary), чтобы его можно было передать как disabledDates.
Есть только одна проблема: boundary — это ClosedRange. Он состоит только из начального и конечного значений, между ними нет значений, поэтому его нельзя преобразовать в список. Чтобы заполнить этот пробел, нам нужен итератор для такого диапазона:
fun ClosedRange<LocalDate>.toIterable(): Iterable<LocalDate> = Iterable {
object : Iterator<LocalDate> {
private var nextDate = start
override fun hasNext(): Boolean = nextDate <= endInclusive
override fun next(): LocalDate = nextDate
.also { nextDate = nextDate.plusDays(1) }
}
}
Теперь мы можем просто удалить разрешенные даты из диапазона дат следующим образом:
boundary.toIterable() - allowedDates
В совокупности это будет выглядеть так:
val boundary = LocalDate.now()..LocalDate.now().plusYears(10)
val allowedDates = setOf(
LocalDate.now().plusDays(3),
LocalDate.now().plusDays(5),
LocalDate.now().plusDays(7),
)
val disabledDates = remember(boundary, allowedDates) {
boundary.toIterable() - allowedDates
}
CalendarView(
useCaseState = rememberUseCaseState(),
config = CalendarConfig(
style = CalendarStyle.MONTH,
disabledDates = disabledDates,
boundary = boundary,
),
selection = CalendarSelection.Date { newDate ->
selectedDate.value = newDate
},
)
disabledDates следует использовать remember, поскольку преобразование диапазона в список может оказаться дорогостоящей операцией, если boundary очень большой. Поэтому это следует делать не при каждой рекомпозиции, а только при изменении boundary или allowedDates.