Skip to content

Commit

Permalink
Merge pull request #126 from wojta/date-restrictions
Browse files Browse the repository at this point in the history
Disabling specific days in date picker
  • Loading branch information
PranavMaganti committed Jan 18, 2022
2 parents e447239 + 847c4be commit 8eea311
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 10 deletions.
Expand Up @@ -12,6 +12,7 @@ import com.vanpra.composematerialdialogs.datetime.date.datepicker
import com.vanpra.composematerialdialogs.datetime.time.TimePickerColors
import com.vanpra.composematerialdialogs.datetime.time.TimePickerDefaults
import com.vanpra.composematerialdialogs.datetime.time.timepicker
import java.time.DayOfWeek
import java.time.LocalTime

/**
Expand Down Expand Up @@ -95,6 +96,17 @@ fun DateTimeDialogDemo() {
println(it.toString())
}
}

DialogAndShowButton(
buttonText = "Date Picker Dialog with date restrictions",
buttons = { defaultDateTimeDialogButtons() }
) {
datepicker(allowedDateValidator = {
it.dayOfWeek !== DayOfWeek.SATURDAY && it.dayOfWeek !== DayOfWeek.SUNDAY
}) {
println(it.toString())
}
}
}

@Composable
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Expand Up @@ -14,7 +14,7 @@ buildscript {

dependencies {
classpath(Dependencies.Kotlin.gradlePlugin)
classpath("com.android.tools.build:gradle:7.1.0-beta04")
classpath("com.android.tools.build:gradle:7.1.0-rc01")
classpath("com.vanniktech:gradle-maven-publish-plugin:0.17.0")
classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.6.0")
classpath(Dependencies.Shot.core)
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Expand Up @@ -9,6 +9,7 @@ import com.vanpra.composematerialdialogs.test.utils.extensions.onDialog
import com.vanpra.composematerialdialogs.test.utils.extensions.setContentAndWaitForIdle
import org.junit.Rule
import org.junit.Test
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.LocalTime

Expand Down Expand Up @@ -62,6 +63,19 @@ class DateTimePickerTest : ScreenshotTest {
compareScreenshot(composeTestRule.onDialog())
}

@Test
fun datePickerWithRestrictedDates() {
composeTestRule.setContentAndWaitForIdle {
DialogWithContent {
datepicker(title = testTitle, initialDate = LocalDate.of(2021, 7, 27), allowedDateValidator = {
it.dayOfWeek != DayOfWeek.SATURDAY && it.dayOfWeek != DayOfWeek.SUNDAY
})
}
}

compareScreenshot(composeTestRule.onDialog())
}

@Test
fun timePickerWithCustomTitle() {
composeTestRule.setContentAndWaitForIdle {
Expand Down
Expand Up @@ -2,6 +2,7 @@ package com.vanpra.composematerialdialogs.datetime.date

import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
Expand All @@ -26,6 +27,7 @@ import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
Expand All @@ -50,6 +52,7 @@ import androidx.compose.ui.text.font.FontWeight.Companion.W600
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.rememberPagerState
Expand All @@ -70,6 +73,7 @@ import java.util.Locale
* @param waitForPositiveButton if true the [onDateChange] callback will only be called when the
* positive button is pressed, otherwise it will be called on every input change
* @param onDateChange callback with a LocalDateTime object when the user completes their input
* @param allowedDateValidator when this returns true the date will be selectable otherwise it won't be
*/
@Composable
fun MaterialDialogScope.datepicker(
Expand All @@ -78,13 +82,14 @@ fun MaterialDialogScope.datepicker(
colors: DatePickerColors = DatePickerDefaults.colors(),
yearRange: IntRange = IntRange(1900, 2100),
waitForPositiveButton: Boolean = true,
allowedDateValidator: (LocalDate) -> Boolean = { true },
onDateChange: (LocalDate) -> Unit = {}
) {
val datePickerState = remember {
DatePickerState(initialDate, colors, yearRange, dialogState.dialogBackgroundColor!!)
}

DatePickerImpl(title = title, state = datePickerState)
DatePickerImpl(title = title, state = datePickerState, allowedDateValidator)

if (waitForPositiveButton) {
DialogCallback { onDateChange(datePickerState.selected) }
Expand All @@ -96,8 +101,9 @@ fun MaterialDialogScope.datepicker(
}
}

@OptIn(ExperimentalPagerApi::class)
@Composable
internal fun DatePickerImpl(title: String, state: DatePickerState) {
internal fun DatePickerImpl(title: String, state: DatePickerState, allowedDateValidator: (LocalDate) -> Boolean) {
val pagerState = rememberPagerState(
initialPage = (state.selected.year - state.yearRange.first) * 12 + state.selected.monthValue - 1
)
Expand Down Expand Up @@ -132,13 +138,14 @@ internal fun DatePickerImpl(title: String, state: DatePickerState) {
YearPicker(viewDate, state, pagerState)
}

CalendarView(viewDate, state)
CalendarView(viewDate, state, allowedDateValidator)
}
}
}
}
}

@OptIn(ExperimentalPagerApi::class, ExperimentalFoundationApi::class)
@Composable
private fun YearPicker(
viewDate: LocalDate,
Expand Down Expand Up @@ -200,6 +207,7 @@ private fun YearPickerItem(
}
}

@OptIn(ExperimentalPagerApi::class)
@Composable
private fun CalendarViewHeader(
viewDate: LocalDate,
Expand Down Expand Up @@ -287,8 +295,9 @@ private fun CalendarViewHeader(
}
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun CalendarView(viewDate: LocalDate, state: DatePickerState) {
private fun CalendarView(viewDate: LocalDate, state: DatePickerState, allowedDateValidator: (LocalDate) -> Boolean) {
Column(
Modifier
.padding(start = 12.dp, end = 12.dp)
Expand All @@ -310,9 +319,10 @@ private fun CalendarView(viewDate: LocalDate, state: DatePickerState) {
val selected = remember(state.selected) {
possibleSelected && it == state.selected.dayOfMonth
}

DateSelectionBox(it, selected, state.colors) {
state.selected = viewDate.withDayOfMonth(it)
val date = viewDate.withDayOfMonth(it)
val enabled = allowedDateValidator(date)
DateSelectionBox(it, selected, state.colors, enabled) {
state.selected = date
}
}
}
Expand All @@ -324,6 +334,7 @@ private fun DateSelectionBox(
date: Int,
selected: Boolean,
colors: DatePickerColors,
enabled: Boolean,
onClick: () -> Unit
) {
Box(
Expand All @@ -332,7 +343,7 @@ private fun DateSelectionBox(
.size(40.dp)
.clickable(
interactionSource = MutableInteractionSource(),
onClick = onClick,
onClick = { if (enabled) onClick() },
indication = null
),
contentAlignment = Alignment.Center
Expand All @@ -343,7 +354,8 @@ private fun DateSelectionBox(
.size(32.dp)
.clip(CircleShape)
.background(colors.backgroundColor(selected).value)
.wrapContentSize(Alignment.Center),
.wrapContentSize(Alignment.Center)
.alpha(if (enabled) ContentAlpha.high else ContentAlpha.disabled),
style = TextStyle(
color = colors.textColor(selected).value,
fontSize = 12.sp
Expand All @@ -352,6 +364,7 @@ private fun DateSelectionBox(
}
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun DayOfWeekHeader() {
Row(
Expand Down

0 comments on commit 8eea311

Please sign in to comment.