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 authored 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.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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.