From 49ebd68b8a833bfc74424d48e02739ed6edb85a7 Mon Sep 17 00:00:00 2001 From: Emir Demirli Date: Tue, 29 Nov 2022 11:49:54 +0300 Subject: [PATCH 1/8] version increased to 1.1.4 --- wheel-picker-compose/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wheel-picker-compose/build.gradle b/wheel-picker-compose/build.gradle index 8d84018..a5be642 100644 --- a/wheel-picker-compose/build.gradle +++ b/wheel-picker-compose/build.gradle @@ -55,7 +55,7 @@ afterEvaluate { groupId = 'com.github.commandiron' artifactId = 'wheel-picker-compose' - version = '1.1.3' + version = '1.1.4' } } } From 2f7e5b41c94941398bc0a0104623b1f9d13c7c06 Mon Sep 17 00:00:00 2001 From: Emir Demirli Date: Tue, 29 Nov 2022 12:46:23 +0300 Subject: [PATCH 2/8] . --- .../core/DefaultWheelTimePicker.kt | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt index 7ac3dd1..ff60d19 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt @@ -30,7 +30,15 @@ internal fun DefaultWheelTimePicker( selectorProperties: SelectorProperties = WheelPickerDefaults.selectorProperties(), onSnappedTime : (snappedTime: SnappedTime) -> Int? = { _ -> null }, ) { - val hourTexts: List = (0..23).map { it.toString().padStart(2, '0') } + + val hours = (0..23).map { + Hour( + text = it.toString().padStart(2, '0'), + value = it, + index = it + ) + } + val minuteTexts: List = (0..59).map { it.toString().padStart(2, '0') } var snappedTime by remember { mutableStateOf(startTime) } @@ -49,7 +57,7 @@ internal fun DefaultWheelTimePicker( //Hour WheelTextPicker( size = DpSize(size.width / 2, size.height), - texts = hourTexts, + texts = hours.map { it.text }, style = textStyle, color = textColor, startIndex = startTime.hour, @@ -57,9 +65,13 @@ internal fun DefaultWheelTimePicker( enabled = false ), onScrollFinished = { snappedIndex -> - try { - val newTime = snappedTime.withHour(snappedIndex) + val newHour = hours.find { it.index == snappedIndex }?.value + + newHour?.let { + + val newTime = snappedTime.withHour(newHour) + val isTimeBefore = isTimeBefore(newTime, startTime) if(backwardsDisabled){ @@ -70,12 +82,16 @@ internal fun DefaultWheelTimePicker( snappedTime = newTime } - onSnappedTime( - SnappedTime.Hour(snappedTime, snappedTime.hour) - )?.let { return@WheelTextPicker it } + val newIndex = hours.find { it.value == snappedTime.hour }?.index - }catch (e: Exception){ - e.printStackTrace() + newIndex?.let { + onSnappedTime( + SnappedTime.Hour( + localTime = snappedTime, + index = newIndex + ) + )?.let { return@WheelTextPicker it } + } } return@WheelTextPicker snappedTime.hour @@ -135,6 +151,12 @@ private fun isTimeBefore(time: LocalTime, currentTime: LocalTime): Boolean{ return time.isBefore(currentTime) } +data class Hour( + val text: String, + val value: Int, + val index: Int +) + From 15f85619b04257887827a7302c2b5c203fd9982d Mon Sep 17 00:00:00 2001 From: Emir Demirli Date: Tue, 29 Nov 2022 16:15:59 +0300 Subject: [PATCH 3/8] . --- .../wheelpickercompose/MainActivity.kt | 6 +- .../core/CalculateMonthDayTexts.kt | 32 --- .../core/DefaultWheelDatePicker.kt | 223 +++++++++++++----- .../core/DefaultWheelTimePicker.kt | 56 +++-- 4 files changed, 211 insertions(+), 106 deletions(-) delete mode 100644 wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/CalculateMonthDayTexts.kt diff --git a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt index f310a7e..0b19a99 100644 --- a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt +++ b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt @@ -41,7 +41,7 @@ class MainActivity : ComponentActivity() { WheelTimePicker { snappedTime -> println(snappedTime) } - WheelDatePicker { snappedDate -> + WheelDatePicker(yearsRange = null) { snappedDate -> println(snappedDate) } WheelDateTimePicker { snappedDateTime -> @@ -51,9 +51,9 @@ class MainActivity : ComponentActivity() { startDateTime = LocalDateTime.of( 2025, 10, 30, 5, 0 ), - yearsRange = IntRange(1950, 2050), + yearsRange = null, size = DpSize(200.dp, 100.dp), - backwardsDisabled = false, + backwardsDisabled = true, textStyle = MaterialTheme.typography.titleSmall, textColor = Color(0xFFffc300), selectorProperties = WheelPickerDefaults.selectorProperties( diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/CalculateMonthDayTexts.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/CalculateMonthDayTexts.kt deleted file mode 100644 index 75b54f6..0000000 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/CalculateMonthDayTexts.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.commandiron.wheel_picker_compose.core - -import android.os.Build -import androidx.annotation.RequiresApi -import java.time.LocalDate - -@RequiresApi(Build.VERSION_CODES.O) -internal fun calculateMonthDayTexts(month: Int, year: Int): List { - - val isLeapYear = LocalDate.of(year, month, 1).isLeapYear - - val month31day = (1..31).toList().map { it.toString() } - val month30day = (1..30).toList().map { it.toString() } - val month29day = (1..29).toList().map { it.toString() } - val month28day = (1..28).toList().map { it.toString() } - - return when(month){ - 1 -> { month31day } - 2 -> { if(isLeapYear) month29day else month28day } - 3 -> { month31day } - 4 -> { month30day } - 5 -> { month31day } - 6 -> { month30day } - 7 -> { month31day } - 8 -> { month31day } - 9 -> { month30day } - 10 -> { month31day } - 11 -> { month30day } - 12 -> { month31day } - else -> { emptyList() } - } -} \ No newline at end of file diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt index 50b3633..1f2fb3a 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt @@ -31,16 +31,27 @@ internal fun DefaultWheelDatePicker( selectorProperties: SelectorProperties = WheelPickerDefaults.selectorProperties(), onSnappedDate : (snappedDate: SnappedDate) -> Int? = { _ -> null } ) { - var dayTexts by remember { mutableStateOf((1..31).toList().map { it.toString() }) } - val monthTexts: List = if(size.width / 3 < 55.dp){ - DateFormatSymbols().shortMonths.toList() - }else{ - DateFormatSymbols().months.toList() - } + var snappedDate by remember { mutableStateOf(startDate) } - val yearTexts = yearsRange?.map { it.toString() } ?: listOf() + var dayOfMonths = calculateDayOfMonths(snappedDate.month.value, snappedDate.year) - var snappedDate by remember { mutableStateOf(startDate) } + val months = (1..12).map { + Month( + text = if(size.width / 3 < 55.dp){ + DateFormatSymbols().shortMonths[it - 1] + } else DateFormatSymbols().months[it - 1], + value = it, + index = it - 1 + ) + } + + val years = yearsRange?.map { + Year( + text = it.toString(), + value = it, + index = yearsRange.indexOf(it) + ) + } Box(modifier = modifier, contentAlignment = Alignment.Center){ if(selectorProperties.enabled().value){ @@ -56,99 +67,136 @@ internal fun DefaultWheelDatePicker( //Day of Month WheelTextPicker( size = DpSize(size.width / 3 / if(yearsRange == null) 2 else 1, size.height), - texts = dayTexts, + texts = dayOfMonths.map { it.text }, style = textStyle, color = textColor, selectorProperties = WheelPickerDefaults.selectorProperties( enabled = false ), - startIndex = startDate.dayOfMonth - 1, + startIndex = dayOfMonths.find { it.value== startDate.dayOfMonth }?.index ?: 0, onScrollFinished = { snappedIndex -> - val newDate = snappedDate.withDayOfMonth(if(snappedIndex + 1 > dayTexts.size) snappedIndex else snappedIndex + 1) - val isDateBefore = isDateBefore(newDate, startDate) + val newDayOfMonth = dayOfMonths.find { it.index == snappedIndex }?.value - if(backwardsDisabled) { - if(!isDateBefore) { + newDayOfMonth?.let { + val newDate = snappedDate.withDayOfMonth(newDayOfMonth) + + val isDateBefore = isDateBefore(newDate, startDate) + + if(backwardsDisabled) { + if(!isDateBefore) { + snappedDate = newDate + } + } else { snappedDate = newDate } - } else { - snappedDate = newDate - } - onSnappedDate( - SnappedDate.DayOfMonth(snappedDate, snappedDate.dayOfMonth - 1) - )?.let { return@WheelTextPicker it } + val newIndex = dayOfMonths.find { it.value == snappedDate.dayOfMonth }?.index - return@WheelTextPicker snappedDate.dayOfMonth - 1 + newIndex?.let { + onSnappedDate( + SnappedDate.DayOfMonth( + localDate = snappedDate, + index = newIndex + ) + )?.let { return@WheelTextPicker it } + } + } + + return@WheelTextPicker dayOfMonths.find { it.value == snappedDate.dayOfMonth }?.index } ) //Month WheelTextPicker( size = DpSize(size.width / 3, size.height), - texts = monthTexts, + texts = months.map { it.text }, style = textStyle, color = textColor, selectorProperties = WheelPickerDefaults.selectorProperties( enabled = false ), - startIndex = startDate.month.value - 1, + startIndex = months.find { it.value== startDate.monthValue }?.index ?: 0, onScrollFinished = { snappedIndex -> - val newDate = snappedDate.withMonth(if(snappedIndex + 1 > 12) 12 else snappedIndex + 1) - val isDateBefore = isDateBefore(newDate, startDate) + val newMonth = months.find { it.index == snappedIndex }?.value + + newMonth?.let { - if(backwardsDisabled) { - if(!isDateBefore) { + val newDate = snappedDate.withMonth(newMonth) + + val isDateBefore = isDateBefore(newDate, startDate) + + if(backwardsDisabled) { + if(!isDateBefore) { + snappedDate = newDate + } + } else { snappedDate = newDate } - } else { - snappedDate = newDate - } - dayTexts = calculateMonthDayTexts(snappedDate.month.value, snappedDate.year) + dayOfMonths = calculateDayOfMonths(snappedDate.month.value, snappedDate.year) - onSnappedDate( - SnappedDate.Month(snappedDate, snappedDate.month.value - 1) - )?.let { return@WheelTextPicker it } + val newIndex = months.find { it.value == snappedDate.monthValue }?.index - return@WheelTextPicker snappedDate.month.value - 1 + newIndex?.let { + onSnappedDate( + SnappedDate.Month( + localDate = snappedDate, + index = newIndex + ) + )?.let { return@WheelTextPicker it } + } + } + + + return@WheelTextPicker months.find { it.value == snappedDate.monthValue }?.index } ) //Year - yearsRange?.let { yearsRange -> + years?.let { years -> WheelTextPicker( size = DpSize(size.width / 3, size.height), - texts = yearTexts, + texts = years.map { it.text }, style = textStyle, color = textColor, selectorProperties = WheelPickerDefaults.selectorProperties( enabled = false ), - startIndex = if(yearsRange.indexOf(yearsRange.find { it == startDate.year }) == -1) { - throw IllegalArgumentException( - "startDate.year should greater than minYear and smaller than maxYear" - ) - } else yearsRange.indexOf(yearsRange.find { it == startDate.year }), + startIndex = years.find { it.value == startDate.year }?.index ?:0, onScrollFinished = { snappedIndex -> - val selectedYearText = yearTexts.getOrNull(snappedIndex) ?: yearTexts.last() - val newDate = snappedDate.withYear(selectedYearText.toInt()) - val isDateBefore = isDateBefore(newDate, startDate) + val newYear = years.find { it.index == snappedIndex }?.value - if(backwardsDisabled) { - if(!isDateBefore) { + newYear?.let { + + val newDate = snappedDate.withYear(newYear) + + val isDateBefore = isDateBefore(newDate, startDate) + + if(backwardsDisabled) { + if(!isDateBefore) { + snappedDate = newDate + } + } else { snappedDate = newDate } - } else { - snappedDate = newDate - } - dayTexts = calculateMonthDayTexts(snappedDate.month.value, snappedDate.year) + dayOfMonths = calculateDayOfMonths(snappedDate.month.value, snappedDate.year) + + val newIndex = years.find { it.value == snappedDate.year }?.index - onSnappedDate(SnappedDate.Year(snappedDate, yearTexts.indexOf(snappedDate.year.toString())))?.let { return@WheelTextPicker it } + newIndex?.let { + onSnappedDate( + SnappedDate.Year( + localDate = snappedDate, + index = newIndex + ) + )?.let { return@WheelTextPicker it } + + } + } - return@WheelTextPicker yearTexts.indexOf(snappedDate.year.toString()) + return@WheelTextPicker years.find { it.value == snappedDate.year }?.index } ) } @@ -159,4 +207,73 @@ internal fun DefaultWheelDatePicker( @RequiresApi(Build.VERSION_CODES.O) private fun isDateBefore(date: LocalDate, currentDate: LocalDate): Boolean{ return date.isBefore(currentDate) +} + +data class DayOfMonth( + val text: String, + val value: Int, + val index: Int +) + +data class Month( + val text: String, + val value: Int, + val index: Int +) + +data class Year( + val text: String, + val value: Int, + val index: Int +) + +@RequiresApi(Build.VERSION_CODES.O) +internal fun calculateDayOfMonths(month: Int, year: Int): List { + + val isLeapYear = LocalDate.of(year, month, 1).isLeapYear + + val month31day = (1..31).map { + DayOfMonth( + text = it.toString(), + value = it, + index = it - 1 + ) + } + val month30day = (1..30).map { + DayOfMonth( + text = it.toString(), + value = it, + index = it - 1 + ) + } + val month29day = (1..29).map { + DayOfMonth( + text = it.toString(), + value = it, + index = it - 1 + ) + } + val month28day = (1..28).map { + DayOfMonth( + text = it.toString(), + value = it, + index = it - 1 + ) + } + + return when(month){ + 1 -> { month31day } + 2 -> { if(isLeapYear) month29day else month28day } + 3 -> { month31day } + 4 -> { month30day } + 5 -> { month31day } + 6 -> { month30day } + 7 -> { month31day } + 8 -> { month31day } + 9 -> { month30day } + 10 -> { month31day } + 11 -> { month30day } + 12 -> { month31day } + else -> { emptyList() } + } } \ No newline at end of file diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt index ff60d19..bae150d 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt @@ -31,6 +31,8 @@ internal fun DefaultWheelTimePicker( onSnappedTime : (snappedTime: SnappedTime) -> Int? = { _ -> null }, ) { + var snappedTime by remember { mutableStateOf(startTime) } + val hours = (0..23).map { Hour( text = it.toString().padStart(2, '0'), @@ -39,9 +41,13 @@ internal fun DefaultWheelTimePicker( ) } - val minuteTexts: List = (0..59).map { it.toString().padStart(2, '0') } - - var snappedTime by remember { mutableStateOf(startTime) } + val minutes = (0..59).map { + Minute( + text = it.toString().padStart(2, '0'), + value = it, + index = it + ) + } Box(modifier = modifier, contentAlignment = Alignment.Center){ if(selectorProperties.enabled().value){ @@ -60,7 +66,7 @@ internal fun DefaultWheelTimePicker( texts = hours.map { it.text }, style = textStyle, color = textColor, - startIndex = startTime.hour, + startIndex = hours.find { it.value == startTime.hour }?.index ?: 0, selectorProperties = WheelPickerDefaults.selectorProperties( enabled = false ), @@ -74,11 +80,11 @@ internal fun DefaultWheelTimePicker( val isTimeBefore = isTimeBefore(newTime, startTime) - if(backwardsDisabled){ - if(!isTimeBefore){ + if (backwardsDisabled) { + if (!isTimeBefore) { snappedTime = newTime } - }else{ + } else { snappedTime = newTime } @@ -94,23 +100,27 @@ internal fun DefaultWheelTimePicker( } } - return@WheelTextPicker snappedTime.hour + return@WheelTextPicker hours.find { it.value == snappedTime.hour }?.index } ) //Minute WheelTextPicker( size = DpSize(size.width / 2, size.height), - texts = minuteTexts, + texts = minutes.map { it.text }, style = textStyle, color = textColor, - startIndex = startTime.minute, + startIndex = minutes.find { it.value == startTime.minute }?.index ?: 0, selectorProperties = WheelPickerDefaults.selectorProperties( enabled = false ), onScrollFinished = { snappedIndex -> - try { - val newTime = snappedTime.withMinute(snappedIndex) + val newMinute = minutes.find { it.index == snappedIndex }?.value + + newMinute?.let { + + val newTime = snappedTime.withMinute(newMinute) + val isTimeBefore = isTimeBefore(newTime, startTime) if(backwardsDisabled){ @@ -121,15 +131,19 @@ internal fun DefaultWheelTimePicker( snappedTime = newTime } - onSnappedTime( - SnappedTime.Minute(snappedTime, snappedTime.minute) - )?.let { return@WheelTextPicker it } + val newIndex = minutes.find { it.value == snappedTime.minute }?.index - }catch (e: Exception){ - e.printStackTrace() + newIndex?.let { + onSnappedTime( + SnappedTime.Minute( + localTime = snappedTime, + index = newIndex + ) + )?.let { return@WheelTextPicker it } + } } - return@WheelTextPicker snappedTime.minute + return@WheelTextPicker minutes.find { it.value == snappedTime.minute }?.index } ) } @@ -157,6 +171,12 @@ data class Hour( val index: Int ) +data class Minute( + val text: String, + val value: Int, + val index: Int +) + From eebd0c73b6daa4aad38689615dba5de5979c52c9 Mon Sep 17 00:00:00 2001 From: Emir Demirli Date: Tue, 29 Nov 2022 16:22:24 +0300 Subject: [PATCH 4/8] . --- .../java/com/commandiron/wheelpickercompose/MainActivity.kt | 2 +- .../wheel_picker_compose/core/DefaultWheelDateTimePicker.kt | 3 ++- .../wheel_picker_compose/core/DefaultWheelTimePicker.kt | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt index 0b19a99..208a183 100644 --- a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt +++ b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt @@ -41,7 +41,7 @@ class MainActivity : ComponentActivity() { WheelTimePicker { snappedTime -> println(snappedTime) } - WheelDatePicker(yearsRange = null) { snappedDate -> + WheelDatePicker { snappedDate -> println(snappedDate) } WheelDateTimePicker { snappedDateTime -> diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDateTimePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDateTimePicker.kt index d947fbd..8da0231 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDateTimePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDateTimePicker.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import java.time.LocalDateTime +import java.time.temporal.ChronoUnit @RequiresApi(Build.VERSION_CODES.O) @Composable @@ -31,7 +32,7 @@ internal fun DefaultWheelDateTimePicker( onSnappedDateTime : (snappedDateTime: SnappedDateTime) -> Int? = { _ -> null } ) { - var snappedDateTime by remember { mutableStateOf(startDateTime) } + var snappedDateTime by remember { mutableStateOf(startDateTime.truncatedTo(ChronoUnit.MINUTES)) } val yearTexts = yearsRange?.map { it.toString() } ?: listOf() diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt index bae150d..040326f 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import java.time.LocalTime +import java.time.temporal.ChronoUnit @RequiresApi(Build.VERSION_CODES.O) @Composable @@ -31,7 +32,7 @@ internal fun DefaultWheelTimePicker( onSnappedTime : (snappedTime: SnappedTime) -> Int? = { _ -> null }, ) { - var snappedTime by remember { mutableStateOf(startTime) } + var snappedTime by remember { mutableStateOf(startTime.truncatedTo(ChronoUnit.MINUTES)) } val hours = (0..23).map { Hour( From 94886ba2a4ae974a3f96f4a61c0accc4bb708342 Mon Sep 17 00:00:00 2001 From: Emir Demirli Date: Tue, 29 Nov 2022 16:48:16 +0300 Subject: [PATCH 5/8] . --- .../core/DefaultWheelDatePicker.kt | 16 +++++++++++++--- .../core/DefaultWheelDateTimePicker.kt | 11 +++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt index 1f2fb3a..c849cf3 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt @@ -2,6 +2,7 @@ package com.commandiron.wheel_picker_compose.core import android.os.Build import androidx.annotation.RequiresApi +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.size @@ -66,7 +67,10 @@ internal fun DefaultWheelDatePicker( Row { //Day of Month WheelTextPicker( - size = DpSize(size.width / 3 / if(yearsRange == null) 2 else 1, size.height), + size = DpSize( + width = if(yearsRange == null) size.width / 2 else size.width / 3, + height = size.height + ), texts = dayOfMonths.map { it.text }, style = textStyle, color = textColor, @@ -108,7 +112,10 @@ internal fun DefaultWheelDatePicker( ) //Month WheelTextPicker( - size = DpSize(size.width / 3, size.height), + size = DpSize( + width = if(yearsRange == null) size.width / 2 else size.width / 3, + height = size.height + ), texts = months.map { it.text }, style = textStyle, color = textColor, @@ -155,7 +162,10 @@ internal fun DefaultWheelDatePicker( //Year years?.let { years -> WheelTextPicker( - size = DpSize(size.width / 3, size.height), + size = DpSize( + width = size.width / 3, + height = size.height + ), texts = years.map { it.text }, style = textStyle, color = textColor, diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDateTimePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDateTimePicker.kt index 8da0231..298dbe2 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDateTimePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDateTimePicker.kt @@ -2,6 +2,7 @@ package com.commandiron.wheel_picker_compose.core import android.os.Build import androidx.annotation.RequiresApi +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.size @@ -52,7 +53,10 @@ internal fun DefaultWheelDateTimePicker( startDate = startDateTime.toLocalDate(), yearsRange = yearsRange, backwardsDisabled = false, - size = DpSize(size.width / 5 * 3, size.height), + size = DpSize( + width = if(yearsRange == null ) size.width * 3 / 6 else size.width * 3 / 5 , + height = size.height + ), textStyle = textStyle, textColor = textColor, selectorProperties = WheelPickerDefaults.selectorProperties( @@ -102,7 +106,10 @@ internal fun DefaultWheelDateTimePicker( DefaultWheelTimePicker( startTime = startDateTime.toLocalTime(), backwardsDisabled = false, - size = DpSize(size.width / 5 * 2, size.height), + size = DpSize( + width = if(yearsRange == null ) size.width * 3 / 6 else size.width * 2 / 5 , + height = size.height + ), textStyle = textStyle, textColor = textColor, selectorProperties = WheelPickerDefaults.selectorProperties( From 6ce581750e8995f5f0bc893abb301f7849f6dd11 Mon Sep 17 00:00:00 2001 From: Emir Demirli Date: Tue, 29 Nov 2022 20:49:47 +0300 Subject: [PATCH 6/8] . --- .../wheelpickercompose/MainActivity.kt | 12 +- .../wheel_picker_compose/WheelTimePicker.kt | 3 + .../core/DefaultWheelDatePicker.kt | 6 +- .../core/DefaultWheelTimePicker.kt | 233 +++++++++++++++--- 4 files changed, 219 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt index 208a183..c166192 100644 --- a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt +++ b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt @@ -20,8 +20,10 @@ import androidx.compose.ui.unit.dp import com.commandiron.wheel_picker_compose.WheelDatePicker import com.commandiron.wheel_picker_compose.WheelDateTimePicker import com.commandiron.wheel_picker_compose.WheelTimePicker +import com.commandiron.wheel_picker_compose.core.TimeFormat import com.commandiron.wheel_picker_compose.core.WheelPickerDefaults import com.commandiron.wheelpickercompose.ui.theme.WheelPickerComposeTheme +import java.sql.Time import java.time.LocalDateTime class MainActivity : ComponentActivity() { @@ -38,14 +40,16 @@ class MainActivity : ComponentActivity() { horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - WheelTimePicker { snappedTime -> + WheelTimePicker( + timeFormat = TimeFormat.AM_PM + ) { snappedTime -> println(snappedTime) } WheelDatePicker { snappedDate -> - println(snappedDate) +// println(snappedDate) } WheelDateTimePicker { snappedDateTime -> - println(snappedDateTime) +// println(snappedDateTime) } WheelDateTimePicker( startDateTime = LocalDateTime.of( @@ -63,7 +67,7 @@ class MainActivity : ComponentActivity() { border = BorderStroke(2.dp, Color(0xFFf1faee)) ) ){ snappedDateTime -> - println(snappedDateTime) +// println(snappedDateTime) } } } 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 5da9cc5..4e8f212 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 @@ -12,6 +12,7 @@ import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import com.commandiron.wheel_picker_compose.core.DefaultWheelTimePicker import com.commandiron.wheel_picker_compose.core.SelectorProperties +import com.commandiron.wheel_picker_compose.core.TimeFormat import com.commandiron.wheel_picker_compose.core.WheelPickerDefaults import java.time.LocalTime @@ -20,6 +21,7 @@ import java.time.LocalTime fun WheelTimePicker( modifier: Modifier = Modifier, startTime: LocalTime = LocalTime.now(), + timeFormat: TimeFormat = TimeFormat.HOUR_24, backwardsDisabled: Boolean = false, size: DpSize = DpSize(128.dp, 128.dp), textStyle: TextStyle = MaterialTheme.typography.titleMedium, @@ -30,6 +32,7 @@ fun WheelTimePicker( DefaultWheelTimePicker( modifier, startTime, + timeFormat, backwardsDisabled, size, textStyle, diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt index c849cf3..ae53b19 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelDatePicker.kt @@ -219,19 +219,19 @@ private fun isDateBefore(date: LocalDate, currentDate: LocalDate): Boolean{ return date.isBefore(currentDate) } -data class DayOfMonth( +internal data class DayOfMonth( val text: String, val value: Int, val index: Int ) -data class Month( +private data class Month( val text: String, val value: Int, val index: Int ) -data class Year( +private data class Year( val text: String, val value: Int, val index: Int diff --git a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt index 040326f..672f6e0 100644 --- a/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt +++ b/wheel-picker-compose/src/main/java/com/commandiron/wheel_picker_compose/core/DefaultWheelTimePicker.kt @@ -24,6 +24,7 @@ import java.time.temporal.ChronoUnit internal fun DefaultWheelTimePicker( modifier: Modifier = Modifier, startTime: LocalTime = LocalTime.now(), + timeFormat: TimeFormat = TimeFormat.HOUR_24, backwardsDisabled: Boolean = false, size: DpSize = DpSize(128.dp, 128.dp), textStyle: TextStyle = MaterialTheme.typography.titleMedium, @@ -41,6 +42,13 @@ internal fun DefaultWheelTimePicker( index = it ) } + val amPmHours = (1..12).map { + AmPmHour( + text = it.toString(), + value = it, + index = it - 1 + ) + } val minutes = (0..59).map { Minute( @@ -50,11 +58,29 @@ internal fun DefaultWheelTimePicker( ) } + val amPms = listOf( + AmPm( + text = "AM", + value = AmPmValue.AM, + index = 0 + ), + AmPm( + text = "PM", + value = AmPmValue.PM, + index = 1 + ) + ) + + var snappedAmPm by remember { + mutableStateOf( + amPms.find { it.value == amPmValueFromTime(startTime) } ?: amPms[0] + ) + } + Box(modifier = modifier, contentAlignment = Alignment.Center){ if(selectorProperties.enabled().value){ Surface( - modifier = Modifier - .size(size.width, size.height / 3), + modifier = Modifier.size(size.width,size.height / 3), shape = selectorProperties.shape().value, color = selectorProperties.color().value, border = selectorProperties.border().value @@ -63,17 +89,29 @@ internal fun DefaultWheelTimePicker( Row { //Hour WheelTextPicker( - size = DpSize(size.width / 2, size.height), - texts = hours.map { it.text }, + size = DpSize( + width = size.width / if(timeFormat == TimeFormat.HOUR_24) 2 else 3, + height = size.height + ), + texts = if(timeFormat == TimeFormat.HOUR_24) hours.map { it.text } else amPmHours.map { it.text }, style = textStyle, color = textColor, - startIndex = hours.find { it.value == startTime.hour }?.index ?: 0, + startIndex = if(timeFormat == TimeFormat.HOUR_24) { + hours.find { it.value == startTime.hour }?.index ?: 0 + } else amPmHours.find { it.value == hourToAmPmHour(startTime.hour) }?.index ?: 0, selectorProperties = WheelPickerDefaults.selectorProperties( enabled = false ), onScrollFinished = { snappedIndex -> - val newHour = hours.find { it.index == snappedIndex }?.value + val newHour = if(timeFormat == TimeFormat.HOUR_24) { + hours.find { it.index == snappedIndex }?.value + } else { + amPmHourToHour( + amPmHours.find { it.index == snappedIndex }?.value ?: 0, + snappedAmPm.value + ) + } newHour?.let { @@ -89,7 +127,11 @@ internal fun DefaultWheelTimePicker( snappedTime = newTime } - val newIndex = hours.find { it.value == snappedTime.hour }?.index + val newIndex = if(timeFormat == TimeFormat.HOUR_24) { + hours.find { it.value == snappedTime.hour }?.index + } else { + amPmHours.find { it.value == hourToAmPmHour(snappedTime.hour)}?.index + } newIndex?.let { onSnappedTime( @@ -101,12 +143,19 @@ internal fun DefaultWheelTimePicker( } } - return@WheelTextPicker hours.find { it.value == snappedTime.hour }?.index + return@WheelTextPicker if(timeFormat == TimeFormat.HOUR_24) { + hours.find { it.value == snappedTime.hour }?.index + } else { + amPmHours.find { it.value == hourToAmPmHour(snappedTime.hour)}?.index + } } ) //Minute WheelTextPicker( - size = DpSize(size.width / 2, size.height), + size = DpSize( + width = size.width / if(timeFormat == TimeFormat.HOUR_24) 2 else 3, + height = size.height + ), texts = minutes.map { it.text }, style = textStyle, color = textColor, @@ -118,38 +167,117 @@ internal fun DefaultWheelTimePicker( val newMinute = minutes.find { it.index == snappedIndex }?.value + val newHour = if(timeFormat == TimeFormat.HOUR_24) { + hours.find { it.value == snappedTime.hour }?.value + } else { + amPmHourToHour( + amPmHours.find { it.value == hourToAmPmHour(snappedTime.hour) }?.value ?: 0, + snappedAmPm.value + ) + } + newMinute?.let { + newHour?.let { + val newTime = snappedTime.withMinute(newMinute).withHour(newHour) - val newTime = snappedTime.withMinute(newMinute) + val isTimeBefore = isTimeBefore(newTime, startTime) - val isTimeBefore = isTimeBefore(newTime, startTime) - - if(backwardsDisabled){ - if(!isTimeBefore){ + if(backwardsDisabled){ + if(!isTimeBefore){ + snappedTime = newTime + } + }else{ snappedTime = newTime } - }else{ - snappedTime = newTime - } - val newIndex = minutes.find { it.value == snappedTime.minute }?.index + val newIndex = minutes.find { it.value == snappedTime.minute }?.index - newIndex?.let { - onSnappedTime( - SnappedTime.Minute( - localTime = snappedTime, - index = newIndex - ) - )?.let { return@WheelTextPicker it } + newIndex?.let { + onSnappedTime( + SnappedTime.Minute( + localTime = snappedTime, + index = newIndex + ) + )?.let { return@WheelTextPicker it } + } } } return@WheelTextPicker minutes.find { it.value == snappedTime.minute }?.index } ) + //AM_PM + if(timeFormat == TimeFormat.AM_PM) { + WheelTextPicker( + size = DpSize( + width = size.width / 3, + height = size.height + ), + texts = amPms.map { it.text }, + style = textStyle, + color = textColor, + startIndex = amPms.find { it.value == amPmValueFromTime(startTime) }?.index ?:0, + selectorProperties = WheelPickerDefaults.selectorProperties( + enabled = false + ), + onScrollFinished = { snappedIndex -> + + val newAmPm = amPms.find { it.index == snappedIndex } + + newAmPm?.let { + snappedAmPm = newAmPm + } + + val newMinute = minutes.find { it.value == snappedTime.minute }?.value + + val newHour = amPmHourToHour( + amPmHours.find { it.value == hourToAmPmHour(snappedTime.hour) }?.value ?: 0, + snappedAmPm.value + ) + + newMinute?.let { + val newTime = snappedTime.withMinute(newMinute).withHour(newHour) + + val isTimeBefore = isTimeBefore(newTime, startTime) + + if(backwardsDisabled){ + if(!isTimeBefore){ + snappedTime = newTime + } + }else{ + snappedTime = newTime + } + + val newIndex = minutes.find { it.value == snappedTime.hour }?.index + + newIndex?.let { + onSnappedTime( + SnappedTime.Hour( + localTime = snappedTime, + index = newIndex + ) + ) + } + } + + return@WheelTextPicker snappedIndex + } + ) + } } Box( - modifier = Modifier.size(size), + modifier = Modifier + .size( + width = if (timeFormat == TimeFormat.HOUR_24) { + size.width + } else size.width * 2 / 3, + height = size.height / 3 + ) + .align( + alignment = if (timeFormat == TimeFormat.HOUR_24) { + Alignment.Center + } else Alignment.CenterStart + ), contentAlignment = Alignment.Center ) { Text( @@ -166,18 +294,67 @@ private fun isTimeBefore(time: LocalTime, currentTime: LocalTime): Boolean{ return time.isBefore(currentTime) } -data class Hour( +enum class TimeFormat { + HOUR_24, AM_PM +} + +private data class Hour( + val text: String, + val value: Int, + val index: Int +) +private data class AmPmHour( val text: String, val value: Int, val index: Int ) -data class Minute( +private fun hourToAmPmHour(hour: Int): Int { + if(hour == 0) { + return 12 + } + if(hour <= 12) { + return hour + } + return hour - 12 +} + +private fun amPmHourToHour(amPmHour: Int, amPmValue: AmPmValue): Int { + return when(amPmValue) { + AmPmValue.AM -> { + amPmHour + } + AmPmValue.PM -> { + if(amPmHour == 12) { + 0 + } else { + amPmHour + 12 + } + } + } +} + +private data class Minute( val text: String, val value: Int, val index: Int ) +private data class AmPm( + val text: String, + val value: AmPmValue, + val index: Int? +) + +internal enum class AmPmValue { + AM, PM +} + +@RequiresApi(Build.VERSION_CODES.O) +private fun amPmValueFromTime(time: LocalTime): AmPmValue { + return if(time.hour > 11) AmPmValue.PM else AmPmValue.AM +} + From c60a4cb49ca9cd6731048e57b343cfe36e8f1d50 Mon Sep 17 00:00:00 2001 From: Emir Demirli Date: Tue, 29 Nov 2022 20:50:00 +0300 Subject: [PATCH 7/8] . --- .../java/com/commandiron/wheelpickercompose/MainActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt index c166192..055b21f 100644 --- a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt +++ b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt @@ -46,10 +46,10 @@ class MainActivity : ComponentActivity() { println(snappedTime) } WheelDatePicker { snappedDate -> -// println(snappedDate) + println(snappedDate) } WheelDateTimePicker { snappedDateTime -> -// println(snappedDateTime) + println(snappedDateTime) } WheelDateTimePicker( startDateTime = LocalDateTime.of( From 4a75e8d4b6be107acd36d4ebe7725daaf1a33e56 Mon Sep 17 00:00:00 2001 From: Emir Demirli Date: Tue, 29 Nov 2022 20:50:28 +0300 Subject: [PATCH 8/8] . --- .../java/com/commandiron/wheelpickercompose/MainActivity.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt index 055b21f..5136924 100644 --- a/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt +++ b/app/src/main/java/com/commandiron/wheelpickercompose/MainActivity.kt @@ -40,9 +40,7 @@ class MainActivity : ComponentActivity() { horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - WheelTimePicker( - timeFormat = TimeFormat.AM_PM - ) { snappedTime -> + WheelTimePicker { snappedTime -> println(snappedTime) } WheelDatePicker { snappedDate -> @@ -67,7 +65,7 @@ class MainActivity : ComponentActivity() { border = BorderStroke(2.dp, Color(0xFFf1faee)) ) ){ snappedDateTime -> -// println(snappedDateTime) + println(snappedDateTime) } } }