diff --git a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt index b14df63..c935595 100644 --- a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt +++ b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt @@ -33,23 +33,26 @@ class MainActivity : ComponentActivity() { horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - WheelDateTimePicker { snappedDate, snappedTime -> } - WheelDatePicker { snappedDate -> } - WheelTimePicker { snappedTime -> } - WheelTextPicker(texts = (1..6).map { it.toString() }) - WheelPicker(count = 6) { index, snappedIndex -> - Card(Modifier.size(128.dp).padding(8.dp)) {} - } -// WheelDateTimePicker( -// size = DpSize(200.dp, 100.dp), -// textStyle = MaterialTheme.typography.titleSmall, -// textColor = Color(0xFFffc300), -// infiniteLoopEnabled = true, -// selectorEnabled = true, -// selectorShape = RoundedCornerShape(0.dp), -// selectorColor = Color(0xFFf1faee).copy(alpha = 0.2f), -// selectorBorder = BorderStroke(2.dp, Color(0xFFf1faee)) -// ) { snappedDate, snappedTime -> } +// WheelDateTimePicker { snappedDate, snappedTime -> +// println(snappedDate) +// println(snappedTime) +// } +// WheelDatePicker { snappedDate -> } +// WheelTimePicker { snappedTime -> } +// WheelTextPicker(texts = (1..6).map { it.toString() }) +// WheelPicker(count = 6) { index, snappedIndex -> +// Card(Modifier.size(128.dp).padding(8.dp)) {} +// } + WheelDateTimePicker( + disablePastDate = true, + size = DpSize(200.dp, 100.dp), + textStyle = MaterialTheme.typography.titleSmall, + textColor = Color(0xFFffc300), + selectorEnabled = true, + selectorShape = RoundedCornerShape(0.dp), + selectorColor = Color(0xFFf1faee).copy(alpha = 0.2f), + selectorBorder = BorderStroke(2.dp, Color(0xFFf1faee)) + ) { snappedDate, snappedTime -> } } } } diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelDatePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelDatePicker.kt index edcf09f..76377d3 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelDatePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelDatePicker.kt @@ -11,6 +11,7 @@ import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -22,32 +23,32 @@ import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import java.text.DateFormatSymbols import java.time.LocalDate +import java.time.LocalTime @RequiresApi(Build.VERSION_CODES.O) @Composable fun WheelDatePicker( modifier: Modifier = Modifier, currentDate: LocalDate = LocalDate.now(), - disableBackwards: Boolean = false, + disablePastDate: Boolean = false, size: DpSize = DpSize(256.dp, 128.dp), textStyle: TextStyle = MaterialTheme.typography.titleMedium, textColor: Color = LocalContentColor.current, - infiniteLoopEnabled: Boolean = false, selectorEnabled: Boolean = true, selectorShape: Shape = RoundedCornerShape(16.dp), selectorColor: Color = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f), selectorBorder: BorderStroke? = BorderStroke(1.dp, MaterialTheme.colorScheme.primary), - onScrollFinished : (snappedDate: LocalDate) -> Unit = {} + onScrollFinished: (snappedDate: LocalDate) -> Unit = {}, ) { val dayTexts = remember { mutableStateOf((1..31).toList().map { it.toString() }) } - val selectedDayOfMonth = remember { mutableStateOf(0)} + val selectedDayOfMonth = remember { mutableStateOf(1)} val monthTexts: List = if(size.width < 250.dp){ DateFormatSymbols().shortMonths.toList() }else{ DateFormatSymbols().months.toList() } - val selectedMonth = remember { mutableStateOf(0)} + val selectedMonth = remember { mutableStateOf(1)} var yearTexts = listOf() val yearRange = 100 @@ -72,21 +73,20 @@ fun WheelDatePicker( texts = dayTexts.value, textStyle = textStyle, textColor = textColor, - infiniteLoopEnabled = infiniteLoopEnabled, selectorEnabled = false, startIndex = currentDate.dayOfMonth - 1, onScrollFinished = { selectedIndex -> - selectedDayOfMonth.value = - if(disableBackwards){ - if(selectedIndex < currentDate.dayOfMonth - 1 ) { - currentDate.dayOfMonth - }else{ - selectedIndex + 1 + try { + selectedDayOfMonth.value = selectedIndex + 1 + val selectedDate = LocalDate.of(selectedYear.value, selectedMonth.value, selectedDayOfMonth.value) + val isDateBefore = isDateBefore(selectedDate, currentDate) + + if(disablePastDate){ + if(isDateBefore){ + selectedDayOfMonth.value = currentDate.dayOfMonth } - }else{ - selectedIndex + 1 } - try { + onScrollFinished( LocalDate.of( selectedYear.value, @@ -97,11 +97,7 @@ fun WheelDatePicker( }catch (e: Exception){ e.printStackTrace() } - if(disableBackwards && selectedIndex < currentDate.dayOfMonth - 1 ) { - return@WheelTextPicker currentDate.dayOfMonth - 1 - }else{ - return@WheelTextPicker selectedIndex - } + return@WheelTextPicker selectedDayOfMonth.value - 1 } ) WheelTextPicker( @@ -109,22 +105,22 @@ fun WheelDatePicker( texts = monthTexts, textStyle = textStyle, textColor = textColor, - infiniteLoopEnabled = infiniteLoopEnabled, selectorEnabled = false, startIndex = currentDate.month.value - 1, onScrollFinished = { selectedIndex -> - selectedMonth.value = - if(disableBackwards){ - if(selectedIndex < currentDate.month.value - 1 ) { - currentDate.month.value - }else{ - selectedIndex + 1 + try { + dayTexts.value = calculateMonthDayTexts(selectedIndex + 1, selectedYear.value) + + selectedMonth.value = selectedIndex + 1 + val selectedDate = LocalDate.of(selectedYear.value, selectedMonth.value, selectedDayOfMonth.value) + val isDateBefore = isDateBefore(selectedDate, currentDate) + + if(disablePastDate){ + if(isDateBefore){ + selectedMonth.value = currentDate.month.value } - }else{ - selectedIndex + 1 } - dayTexts.value = calculateMonthDayTexts(selectedMonth.value, selectedYear.value) - try { + onScrollFinished( LocalDate.of( selectedYear.value, @@ -135,11 +131,7 @@ fun WheelDatePicker( }catch (e: Exception){ e.printStackTrace() } - if(disableBackwards && selectedIndex < currentDate.month.value - 1 ) { - return@WheelTextPicker currentDate.month.value - 1 - }else{ - return@WheelTextPicker selectedIndex - } + return@WheelTextPicker selectedMonth.value - 1 } ) WheelTextPicker( @@ -147,22 +139,22 @@ fun WheelDatePicker( texts = yearTexts, textStyle = textStyle, textColor = textColor, - infiniteLoopEnabled = infiniteLoopEnabled, selectorEnabled = false, startIndex = yearRange, onScrollFinished = { selectedIndex -> - selectedYear.value = - if(disableBackwards){ - if(yearTexts[selectedIndex].toInt() < currentDate.year ) { - yearTexts[yearRange].toInt() - }else{ - yearTexts[selectedIndex].toInt() + try { + dayTexts.value = calculateMonthDayTexts(selectedMonth.value, yearTexts[selectedIndex].toInt()) + + selectedYear.value = yearTexts[selectedIndex].toInt() + val selectedDate = LocalDate.of(selectedYear.value, selectedMonth.value, selectedDayOfMonth.value) + val isDateBefore = isDateBefore(selectedDate, currentDate) + + if(disablePastDate){ + if(isDateBefore){ + selectedYear.value = yearTexts[yearRange].toInt() } - }else{ - yearTexts[selectedIndex].toInt() } - dayTexts.value = calculateMonthDayTexts(selectedMonth.value, selectedYear.value) - try { + onScrollFinished( LocalDate.of( selectedYear.value, @@ -173,11 +165,8 @@ fun WheelDatePicker( }catch (e: Exception){ e.printStackTrace() } - if(disableBackwards && yearTexts[selectedIndex].toInt() < currentDate.year ) { - return@WheelTextPicker yearRange - }else{ - return@WheelTextPicker selectedIndex - } + + return@WheelTextPicker yearTexts.indexOf(selectedYear.value.toString()) } ) } @@ -209,4 +198,9 @@ private fun calculateMonthDayTexts(month: Int, year: Int): List { 12 -> { month31day } else -> { emptyList() } } +} + +@RequiresApi(Build.VERSION_CODES.O) +private fun isDateBefore(date: LocalDate, currentDate: LocalDate): Boolean{ + return date.isBefore(currentDate) } \ No newline at end of file diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelDateTimePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelDateTimePicker.kt index dddcb5b..9e2d8ab 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelDateTimePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelDateTimePicker.kt @@ -29,12 +29,11 @@ import java.time.LocalTime fun WheelDateTimePicker( modifier: Modifier = Modifier, currentDateTime: LocalDateTime = LocalDateTime.now(), - disableDateBackwards: Boolean = false, - disableTimeBackwards: Boolean = false, + disablePastDate: Boolean = false, + disablePastTime: Boolean = false, size: DpSize = DpSize(256.dp, 128.dp), textStyle: TextStyle = MaterialTheme.typography.titleMedium, textColor: Color = LocalContentColor.current, - infiniteLoopEnabled: Boolean = false, selectorEnabled: Boolean = true, selectorShape: Shape = RoundedCornerShape(16.dp), selectorColor: Color = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f), @@ -56,24 +55,21 @@ fun WheelDateTimePicker( Row { WheelDatePicker( currentDate = currentDateTime.toLocalDate(), - disableBackwards = disableDateBackwards, + disablePastDate = disablePastDate, size = DpSize(size.width * 2 / 3, size.height), textStyle = textStyle, textColor = textColor, - infiniteLoopEnabled = infiniteLoopEnabled, selectorEnabled = false, - onScrollFinished = { - currentDate.value = it - onScrollFinished(currentDate.value, currentTime.value) - } - ) + ) { snappedDate -> + currentDate.value = snappedDate + onScrollFinished(currentDate.value, currentTime.value) + } WheelTimePicker( currentTime = currentDateTime.toLocalTime(), - disableBackwards = disableTimeBackwards, + disablePastTime = disablePastTime, size = DpSize(size.width / 3, size.height), textStyle = textStyle, textColor = textColor, - infiniteLoopEnabled = infiniteLoopEnabled, selectorEnabled = false, onScrollFinished = { currentTime.value = it diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelPicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelPicker.kt index 8382a47..f219606 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelPicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelPicker.kt @@ -23,7 +23,6 @@ fun WheelPicker( size: DpSize = DpSize(128.dp, 128.dp), startIndex: Int = 0, count: Int, - infiniteLoopEnabled: Boolean = false, selectorEnabled: Boolean = false, selectorShape: Shape = RoundedCornerShape(0.dp), selectorColor: Color = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f), @@ -38,11 +37,7 @@ fun WheelPicker( val snappedItem = layoutInfo.currentItem snappedItem?.let { snapperLayoutItemInfo -> if(snapperLayoutItemInfo.offset == 0){ - if(infiniteLoopEnabled){ - snappedIndex.value = snapperLayoutItemInfo.index % count - }else{ - snappedIndex.value = snapperLayoutItemInfo.index - } + snappedIndex.value = snapperLayoutItemInfo.index }else{ snappedIndex.value = snapperLayoutItemInfo.index + 1 } @@ -81,8 +76,7 @@ fun WheelPicker( lazyListState = lazyListState ) ){ - items(if(infiniteLoopEnabled) Int.MAX_VALUE else count){ indexInLazyColumn -> - val index = indexInLazyColumn % count + items(count){ index -> Box( modifier = Modifier .height(size.height / 3) diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelTextPicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelTextPicker.kt index 984d918..5729abf 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelTextPicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelTextPicker.kt @@ -21,7 +21,6 @@ fun WheelTextPicker( texts: List, textStyle: TextStyle = MaterialTheme.typography.titleMedium, textColor: Color = LocalContentColor.current, - infiniteLoopEnabled: Boolean = false, selectorEnabled: Boolean = true, selectorShape: Shape = RoundedCornerShape(16.dp), selectorColor: Color = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f), @@ -33,7 +32,6 @@ fun WheelTextPicker( size = size, startIndex = startIndex, count = texts.size, - infiniteLoopEnabled = infiniteLoopEnabled, selectorEnabled = selectorEnabled, selectorShape = selectorShape, selectorColor = selectorColor, diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelTimePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelTimePicker.kt index 1165d1a..a7fb359 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelTimePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/WheelTimePicker.kt @@ -28,11 +28,10 @@ import java.time.LocalTime fun WheelTimePicker( modifier: Modifier = Modifier, currentTime: LocalTime = LocalTime.now(), - disableBackwards: Boolean = false, + disablePastTime: Boolean = false, size: DpSize = DpSize(128.dp, 128.dp), textStyle: TextStyle = MaterialTheme.typography.titleMedium, textColor: Color = LocalContentColor.current, - infiniteLoopEnabled: Boolean = false, selectorEnabled: Boolean = true, selectorShape: Shape = RoundedCornerShape(16.dp), selectorColor: Color = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f), @@ -69,18 +68,19 @@ fun WheelTimePicker( texts = hourTexts, textStyle = textStyle, textColor = textColor, - infiniteLoopEnabled = infiniteLoopEnabled, startIndex = currentTime.hour, selectorEnabled = false, onScrollFinished = { selectedIndex -> - selectedHour.value = - if(disableBackwards){ - if(selectedIndex < currentTime.hour ) { - currentTime.hour - } else selectedIndex - }else{ - selectedIndex + selectedHour.value = selectedIndex + val selectedTime = LocalTime.of(selectedHour.value, selectedMinute.value) + val isTimeBefore = isTimeBefore(selectedTime, currentTime) + + if(disablePastTime){ + if(isTimeBefore){ + selectedHour.value = currentTime.hour } + } + try { onScrollFinished( LocalTime.of( @@ -91,15 +91,7 @@ fun WheelTimePicker( }catch (e: Exception){ e.printStackTrace() } - if(disableBackwards){ - if(selectedIndex < currentTime.hour ) { - return@WheelTextPicker currentTime.hour - }else{ - return@WheelTextPicker selectedIndex - } - }else{ - return@WheelTextPicker selectedIndex - } + return@WheelTextPicker selectedHour.value } ) WheelTextPicker( @@ -107,18 +99,19 @@ fun WheelTimePicker( texts = minuteTexts, textStyle = textStyle, textColor = textColor, - infiniteLoopEnabled = infiniteLoopEnabled, startIndex = currentTime.minute, selectorEnabled = false, onScrollFinished = { selectedIndex -> - selectedMinute.value = - if(disableBackwards){ - if(selectedIndex < currentTime.minute ) { - currentTime.minute - } else selectedIndex - }else{ - selectedIndex + selectedMinute.value = selectedIndex + val selectedTime = LocalTime.of(selectedHour.value, selectedMinute.value) + val isTimeBefore = isTimeBefore(selectedTime, currentTime) + + if(disablePastTime){ + if(isTimeBefore){ + selectedMinute.value = currentTime.minute } + } + try { onScrollFinished( LocalTime.of( @@ -129,15 +122,8 @@ fun WheelTimePicker( }catch (e: Exception){ e.printStackTrace() } - if(disableBackwards){ - if(selectedIndex < currentTime.minute ) { - return@WheelTextPicker currentTime.minute - }else{ - return@WheelTextPicker selectedIndex - } - }else{ - return@WheelTextPicker selectedIndex - } + + return@WheelTextPicker selectedMinute.value } ) } @@ -154,6 +140,11 @@ fun WheelTimePicker( } } +@RequiresApi(Build.VERSION_CODES.O) +private fun isTimeBefore(time: LocalTime, currentTime: LocalTime): Boolean{ + return time.isBefore(currentTime) +} +