diff --git a/picker/src/main/java/com/composepicker/picker/component/ScrollSelector.kt b/picker/src/main/java/com/composepicker/picker/component/ScrollSelector.kt index 6bb8638..5ce2d71 100644 --- a/picker/src/main/java/com/composepicker/picker/component/ScrollSelector.kt +++ b/picker/src/main/java/com/composepicker/picker/component/ScrollSelector.kt @@ -29,12 +29,13 @@ import kotlinx.coroutines.flow.map @Composable fun ScrollableSelector( modifier: Modifier, - valueList: List, - value: Int, + valueList: List, + value: String, limit: Int = 3, suffix: @Composable (() -> Unit) = {}, - onValueChanged: (Int) -> Unit, + onValueChanged: (String) -> Unit, isYear: Boolean = false, + is24Hour: Boolean = true, arrangement: Dp = 8.dp, highlightFontColor: Color = Color.Black, fontColor: Color = Color.DarkGray, @@ -42,12 +43,12 @@ fun ScrollableSelector( textStyle: TextStyle = MaterialTheme.typography.titleSmall, ) { - require(limit % 2 != 0) { "limit Must be Odd."} + require(limit % 2 != 0) { "limit Must be Odd." } Row( modifier = modifier, verticalAlignment = Alignment.CenterVertically ) { - if (isYear) { + if (isYear || is24Hour.not()) { FiniteLazyColumn( modifier = modifier, valueList = valueList, @@ -71,29 +72,32 @@ fun ScrollableSelector( @Composable fun FiniteLazyColumn( modifier: Modifier = Modifier, - valueList: List, - value: Int, + valueList: List, + value: String, limit: Int, arrangement: Dp = 8.dp, highlightFontColor: Color = Color.Black, fontColor: Color = Color.DarkGray, highlightTextStyle: TextStyle = MaterialTheme.typography.titleMedium, textStyle: TextStyle = MaterialTheme.typography.titleSmall, - onValueChanged: (Int) -> Unit, + onValueChanged: (String) -> Unit, ) { val yearValueList = valueList.toMutableList() - yearValueList.add(yearValueList.lastIndex + 1, 0) - yearValueList.add(yearValueList.lastIndex + 1, 0) - yearValueList.add(0, 0) - yearValueList.add(0, 0) + val halfLimit = limit / 2 + + repeat(halfLimit) { + yearValueList.add(0, "0") + yearValueList.add(yearValueList.lastIndex + 1, "0") + } val unSelectLineHeight = (textStyle.lineHeight * (limit - 1)) - val lineHeight = rememberUpdatedState(newValue = unSelectLineHeight.value + highlightTextStyle.lineHeight.value + (arrangement.value * (limit - 2))) + val lineHeight = + rememberUpdatedState(newValue = unSelectLineHeight.value + highlightTextStyle.lineHeight.value + (arrangement.value * (halfLimit))) val listState = - rememberLazyListState(initialFirstVisibleItemIndex = (yearValueList.indexOf(value) - 2)) - val centerIndex = remember { mutableStateOf((listState.firstVisibleItemIndex + 2)) } + rememberLazyListState(initialFirstVisibleItemIndex = (yearValueList.indexOf(value) - halfLimit)) + val centerIndex = remember { mutableStateOf((listState.firstVisibleItemIndex + halfLimit)) } val centerItem = remember { mutableStateOf(yearValueList[centerIndex.value]) } val flingBehavior = rememberSnapFlingBehavior(lazyListState = listState) @@ -108,7 +112,7 @@ fun FiniteLazyColumn( val item = yearValueList[index] Row { - if (item != 0) { + if (item != "0") { if (item == centerItem.value) { Text(text = "$item", style = highlightTextStyle, color = highlightFontColor) } else { @@ -124,7 +128,7 @@ fun FiniteLazyColumn( // call center value LaunchedEffect(listState) { snapshotFlow { listState.firstVisibleItemIndex }.distinctUntilChanged().map { - (it % yearValueList.size) + limit / 2 + (it % yearValueList.size) + halfLimit }.collectLatest { index -> centerIndex.value = index % yearValueList.size centerItem.value = yearValueList[centerIndex.value] @@ -137,20 +141,21 @@ fun FiniteLazyColumn( @Composable internal fun InfiniteLazyColumn( modifier: Modifier = Modifier, - valueList: List, - value: Int, + valueList: List, + value: String, limit: Int, arrangement: Dp = 8.dp, - onValueChanged: (Int) -> Unit, + onValueChanged: (String) -> Unit, highlightFontColor: Color = Color.Black, fontColor: Color = Color.DarkGray, highlightTextStyle: TextStyle = MaterialTheme.typography.titleMedium, textStyle: TextStyle = MaterialTheme.typography.titleSmall, ) { val unSelectLineHeight = (textStyle.lineHeight * (limit - 1)) - val lineHeight = rememberUpdatedState(newValue = unSelectLineHeight.value + highlightTextStyle.lineHeight.value + (arrangement.value * (limit - 2))) + val lineHeight = + rememberUpdatedState(newValue = unSelectLineHeight.value + highlightTextStyle.lineHeight.value + (arrangement.value * (limit - 2))) val listState = rememberLazyListState( - initialFirstVisibleItemIndex = (value + valueList.size - (limit / 2) - 1) % valueList.size + initialFirstVisibleItemIndex = (value.toInt() + valueList.size - (limit / 2) - 1) % valueList.size ) val centerIndex = remember { mutableStateOf((listState.firstVisibleItemIndex + limit / 2) % valueList.size) } diff --git a/picker/src/main/java/com/composepicker/picker/timepicker/ProgTimePicker.kt b/picker/src/main/java/com/composepicker/picker/timepicker/ProgTimePicker.kt index e10a370..63e9c64 100644 --- a/picker/src/main/java/com/composepicker/picker/timepicker/ProgTimePicker.kt +++ b/picker/src/main/java/com/composepicker/picker/timepicker/ProgTimePicker.kt @@ -1,9 +1,17 @@ package com.composepicker.picker.timepicker import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp import com.composepicker.picker.component.ScrollableSelector @Suppress("UNUSED") @@ -13,7 +21,12 @@ fun ProgTimePicker( timePickerState: ProgTimePickerState, hourSuffix: @Composable () -> Unit = {}, minuteSuffix: @Composable () -> Unit = {}, - onTimeChanged: (hour: String, minute: String, meridiem: String) -> Unit + onTimeChanged: (hour: String, minute: String, meridiem: String) -> Unit, + arrangement: Dp = 8.dp, + highlightFontColor: Color = Color.Black, + fontColor: Color = Color.DarkGray, + highlightTextStyle: TextStyle = MaterialTheme.typography.titleMedium, + textStyle: TextStyle = MaterialTheme.typography.titleSmall ) { Row(modifier = modifier) { @@ -22,7 +35,13 @@ fun ProgTimePicker( valueList = timePickerState.hourList, value = timePickerState.hour, suffix = hourSuffix, - onValueChanged = { onTimeChanged(it, timePickerState.minute, timePickerState.meridiem) }) + onValueChanged = { + onTimeChanged( + it, + timePickerState.minute, + timePickerState.meridiem + ) + }) ScrollableSelector( modifier = modifier, @@ -37,7 +56,13 @@ fun ProgTimePicker( valueList = timePickerState.meridiemList, value = timePickerState.meridiem, suffix = minuteSuffix, - onValueChanged = { onTimeChanged(timePickerState.hour, timePickerState.minute, it) }, + onValueChanged = { + onTimeChanged( + timePickerState.hour, + timePickerState.minute, + it + ) + }, is24Hour = false ) } @@ -47,8 +72,14 @@ fun ProgTimePicker( @Preview @Composable fun PreviewProgTimePicker() { - ProgTimePicker( - timePickerState = ProgTimePickerState(1, 1, is24Hour = true, timeGap = TimeGap.FIVE), - onTimeChanged = { a, b, c -> } - ) + Surface( + modifier = Modifier.padding(12.dp), + color = Color.Gray, + shape = RoundedCornerShape(1) + ) { + ProgTimePicker( + timePickerState = ProgTimePickerState(1, 30, is24Hour = false, timeGap = TimeGap.ONE_THIRD), + onTimeChanged = { a, b, c -> } + ) + } } \ No newline at end of file diff --git a/picker/src/main/java/com/composepicker/picker/timepicker/ProgTimePickerState.kt b/picker/src/main/java/com/composepicker/picker/timepicker/ProgTimePickerState.kt index 1b0b774..1617d7c 100644 --- a/picker/src/main/java/com/composepicker/picker/timepicker/ProgTimePickerState.kt +++ b/picker/src/main/java/com/composepicker/picker/timepicker/ProgTimePickerState.kt @@ -3,7 +3,6 @@ package com.composepicker.picker.timepicker import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.Saver import androidx.compose.runtime.saveable.rememberSaveable @@ -13,18 +12,19 @@ import androidx.compose.runtime.setValue class ProgTimePickerState( initialHour: Int, initialMinute: Int, + initialMeridiem: String = "AM", val is24Hour: Boolean = false, val timeGap: TimeGap = TimeGap.ONE ) { init { require(initialHour in 0..23) { "initialHour should in [0..23] range" } require(initialMinute in 0..59) { "initialMinute should be in [0..59] range" } - require(initialMinute % timeGap.interval != 0) { "initialMinute should be matched with timeGap interval."} + require(initialMinute % timeGap.interval == 0) { "initialMinute should be matched with timeGap interval." } } var hour by mutableStateOf(initialHour.toString()) var minute by mutableStateOf(initialMinute.toString()) - var meridiem by mutableStateOf("AM") + var meridiem by mutableStateOf(initialMeridiem) val hourList: List = if (is24Hour) (0..23).map { it.toString() } else (1..12).map { it.toString() } @@ -48,8 +48,9 @@ class ProgTimePickerState( ProgTimePickerState( initialHour = value[0] as Int, initialMinute = value[1] as Int, - is24Hour = value[2] as Boolean, - timeGap = value[3] as TimeGap, + initialMeridiem = value[2] as String, + is24Hour = value[3] as Boolean, + timeGap = value[4] as TimeGap, ) } ) @@ -62,12 +63,14 @@ class ProgTimePickerState( fun rememberProgTimePickerState( initialHour: Int = 0, initialMinute: Int = 0, + initialMeridiem: String = "AM", is24Hour: Boolean = false, timeGap: TimeGap = TimeGap.ONE ): ProgTimePickerState = rememberSaveable(saver = ProgTimePickerState.Saver()) { ProgTimePickerState( initialHour, initialMinute, + initialMeridiem, is24Hour, timeGap )