mirror of
https://git.mihon.tech/mihonapp/mihon
synced 2024-11-29 02:58:51 +03:00
WheelPicker: Add manual input (#9338)
This commit is contained in:
parent
bfb7b5afd5
commit
60d8650860
5 changed files with 159 additions and 177 deletions
|
@ -84,6 +84,7 @@ fun AdaptiveSheet(
|
||||||
onDismissRequest = onDismissRequest,
|
onDismissRequest = onDismissRequest,
|
||||||
properties = DialogProperties(
|
properties = DialogProperties(
|
||||||
usePlatformDefaultWidth = false,
|
usePlatformDefaultWidth = false,
|
||||||
|
decorFitsSystemWindows = false,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
AdaptiveSheetImpl(
|
AdaptiveSheetImpl(
|
||||||
|
|
|
@ -52,8 +52,8 @@ import tachiyomi.domain.library.service.LibraryPreferences.Companion.DEVICE_ONLY
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_HAS_UNREAD
|
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_HAS_UNREAD
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED
|
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ
|
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ
|
||||||
import tachiyomi.presentation.core.components.WheelPicker
|
|
||||||
import tachiyomi.presentation.core.components.WheelPickerDefaults
|
import tachiyomi.presentation.core.components.WheelPickerDefaults
|
||||||
|
import tachiyomi.presentation.core.components.WheelTextPicker
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
@ -334,28 +334,25 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
WheelPickerDefaults.Background(size = DpSize(maxWidth, maxHeight))
|
WheelPickerDefaults.Background(size = DpSize(maxWidth, 128.dp))
|
||||||
|
|
||||||
val size = DpSize(width = maxWidth / 2, height = 128.dp)
|
val size = DpSize(width = maxWidth / 2, height = 128.dp)
|
||||||
Row {
|
Row {
|
||||||
WheelPicker(
|
val columns = (0..10).map { getColumnValue(value = it) }
|
||||||
size = size,
|
WheelTextPicker(
|
||||||
count = 11,
|
|
||||||
startIndex = portraitValue,
|
startIndex = portraitValue,
|
||||||
|
items = columns,
|
||||||
|
size = size,
|
||||||
onSelectionChanged = onPortraitChange,
|
onSelectionChanged = onPortraitChange,
|
||||||
backgroundContent = null,
|
backgroundContent = null,
|
||||||
) { index ->
|
)
|
||||||
WheelPickerDefaults.Item(text = getColumnValue(value = index))
|
WheelTextPicker(
|
||||||
}
|
|
||||||
WheelPicker(
|
|
||||||
size = size,
|
|
||||||
count = 11,
|
|
||||||
startIndex = landscapeValue,
|
startIndex = landscapeValue,
|
||||||
|
items = columns,
|
||||||
|
size = size,
|
||||||
onSelectionChanged = onLandscapeChange,
|
onSelectionChanged = onLandscapeChange,
|
||||||
backgroundContent = null,
|
backgroundContent = null,
|
||||||
) { index ->
|
)
|
||||||
WheelPickerDefaults.Item(text = getColumnValue(value = index))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||||
|
import tachiyomi.presentation.core.components.WheelNumberPicker
|
||||||
import tachiyomi.presentation.core.components.WheelTextPicker
|
import tachiyomi.presentation.core.components.WheelTextPicker
|
||||||
import tachiyomi.presentation.core.components.material.AlertDialogContent
|
import tachiyomi.presentation.core.components.material.AlertDialogContent
|
||||||
import tachiyomi.presentation.core.components.material.Divider
|
import tachiyomi.presentation.core.components.material.Divider
|
||||||
|
@ -96,10 +97,10 @@ fun TrackChapterSelector(
|
||||||
BaseSelector(
|
BaseSelector(
|
||||||
title = stringResource(R.string.chapters),
|
title = stringResource(R.string.chapters),
|
||||||
content = {
|
content = {
|
||||||
WheelTextPicker(
|
WheelNumberPicker(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
startIndex = selection,
|
startIndex = selection,
|
||||||
texts = range.map { "$it" },
|
items = range.toList(),
|
||||||
onSelectionChanged = { onSelectionChange(it) },
|
onSelectionChanged = { onSelectionChange(it) },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -122,7 +123,7 @@ fun TrackScoreSelector(
|
||||||
WheelTextPicker(
|
WheelTextPicker(
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier = Modifier.align(Alignment.Center),
|
||||||
startIndex = selections.indexOf(selection).coerceAtLeast(0),
|
startIndex = selections.indexOf(selection).coerceAtLeast(0),
|
||||||
texts = selections,
|
items = selections,
|
||||||
onSelectionChanged = { onSelectionChange(selections[it]) },
|
onSelectionChanged = { onSelectionChange(selections[it]) },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,15 +4,17 @@ import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
|
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyItemScope
|
import androidx.compose.foundation.lazy.LazyItemScope
|
||||||
import androidx.compose.foundation.lazy.LazyListItemInfo
|
import androidx.compose.foundation.lazy.LazyListItemInfo
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -20,89 +22,39 @@ import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
|
import androidx.compose.ui.text.TextRange
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import java.text.DateFormatSymbols
|
import tachiyomi.presentation.core.util.clearFocusOnSoftKeyboardHide
|
||||||
import java.time.LocalDate
|
import tachiyomi.presentation.core.util.clickableNoIndication
|
||||||
|
import tachiyomi.presentation.core.util.showSoftKeyboard
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun WheelPicker(
|
fun WheelNumberPicker(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
startIndex: Int = 0,
|
startIndex: Int = 0,
|
||||||
count: Int,
|
items: List<Number>,
|
||||||
size: DpSize = DpSize(128.dp, 128.dp),
|
|
||||||
onSelectionChanged: (index: Int) -> Unit = {},
|
|
||||||
backgroundContent: (@Composable (size: DpSize) -> Unit)? = {
|
|
||||||
WheelPickerDefaults.Background(size = it)
|
|
||||||
},
|
|
||||||
itemContent: @Composable LazyItemScope.(index: Int) -> Unit,
|
|
||||||
) {
|
|
||||||
val lazyListState = rememberLazyListState(startIndex)
|
|
||||||
val haptic = LocalHapticFeedback.current
|
|
||||||
|
|
||||||
LaunchedEffect(lazyListState, onSelectionChanged) {
|
|
||||||
snapshotFlow { lazyListState.firstVisibleItemScrollOffset }
|
|
||||||
.map { calculateSnappedItemIndex(lazyListState) }
|
|
||||||
.distinctUntilChanged()
|
|
||||||
.drop(1)
|
|
||||||
.collectLatest {
|
|
||||||
haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove)
|
|
||||||
onSelectionChanged(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = modifier,
|
|
||||||
contentAlignment = Alignment.Center,
|
|
||||||
) {
|
|
||||||
backgroundContent?.invoke(size)
|
|
||||||
|
|
||||||
LazyColumn(
|
|
||||||
modifier = Modifier
|
|
||||||
.height(size.height)
|
|
||||||
.width(size.width),
|
|
||||||
state = lazyListState,
|
|
||||||
contentPadding = PaddingValues(vertical = size.height / RowCount * ((RowCount - 1) / 2)),
|
|
||||||
flingBehavior = rememberSnapFlingBehavior(lazyListState = lazyListState),
|
|
||||||
) {
|
|
||||||
items(count) { index ->
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.height(size.height / RowCount)
|
|
||||||
.width(size.width)
|
|
||||||
.alpha(
|
|
||||||
calculateAnimatedAlpha(
|
|
||||||
lazyListState = lazyListState,
|
|
||||||
index = index,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
contentAlignment = Alignment.Center,
|
|
||||||
) {
|
|
||||||
itemContent(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun WheelTextPicker(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
startIndex: Int = 0,
|
|
||||||
texts: List<String>,
|
|
||||||
size: DpSize = DpSize(128.dp, 128.dp),
|
size: DpSize = DpSize(128.dp, 128.dp),
|
||||||
onSelectionChanged: (index: Int) -> Unit = {},
|
onSelectionChanged: (index: Int) -> Unit = {},
|
||||||
backgroundContent: (@Composable (size: DpSize) -> Unit)? = {
|
backgroundContent: (@Composable (size: DpSize) -> Unit)? = {
|
||||||
|
@ -112,122 +64,150 @@ fun WheelTextPicker(
|
||||||
WheelPicker(
|
WheelPicker(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
startIndex = startIndex,
|
startIndex = startIndex,
|
||||||
count = remember(texts) { texts.size },
|
items = items,
|
||||||
size = size,
|
size = size,
|
||||||
onSelectionChanged = onSelectionChanged,
|
onSelectionChanged = onSelectionChanged,
|
||||||
|
manualInputType = KeyboardType.Number,
|
||||||
backgroundContent = backgroundContent,
|
backgroundContent = backgroundContent,
|
||||||
) {
|
) {
|
||||||
WheelPickerDefaults.Item(text = texts[it])
|
WheelPickerDefaults.Item(text = "$it")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun WheelDatePicker(
|
fun WheelTextPicker(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
startDate: LocalDate = LocalDate.now(),
|
startIndex: Int = 0,
|
||||||
minDate: LocalDate? = null,
|
items: List<String>,
|
||||||
maxDate: LocalDate? = null,
|
size: DpSize = DpSize(128.dp, 128.dp),
|
||||||
size: DpSize = DpSize(256.dp, 128.dp),
|
onSelectionChanged: (index: Int) -> Unit = {},
|
||||||
backgroundContent: (@Composable (size: DpSize) -> Unit)? = {
|
backgroundContent: (@Composable (size: DpSize) -> Unit)? = {
|
||||||
WheelPickerDefaults.Background(size = it)
|
WheelPickerDefaults.Background(size = it)
|
||||||
},
|
},
|
||||||
onSelectionChanged: (date: LocalDate) -> Unit = {},
|
|
||||||
) {
|
) {
|
||||||
var internalSelection by remember { mutableStateOf(startDate) }
|
WheelPicker(
|
||||||
val internalOnSelectionChange: (LocalDate) -> Unit = {
|
modifier = modifier,
|
||||||
internalSelection = it
|
startIndex = startIndex,
|
||||||
onSelectionChanged(internalSelection)
|
items = items,
|
||||||
|
size = size,
|
||||||
|
onSelectionChanged = onSelectionChanged,
|
||||||
|
backgroundContent = backgroundContent,
|
||||||
|
) {
|
||||||
|
WheelPickerDefaults.Item(text = it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun <T> WheelPicker(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
startIndex: Int = 0,
|
||||||
|
items: List<T>,
|
||||||
|
size: DpSize = DpSize(128.dp, 128.dp),
|
||||||
|
onSelectionChanged: (index: Int) -> Unit = {},
|
||||||
|
manualInputType: KeyboardType? = null,
|
||||||
|
backgroundContent: (@Composable (size: DpSize) -> Unit)? = {
|
||||||
|
WheelPickerDefaults.Background(size = it)
|
||||||
|
},
|
||||||
|
itemContent: @Composable LazyItemScope.(item: T) -> Unit,
|
||||||
|
) {
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
val lazyListState = rememberLazyListState(startIndex)
|
||||||
|
|
||||||
|
var internalIndex by remember { mutableStateOf(startIndex) }
|
||||||
|
val internalOnSelectionChanged: (Int) -> Unit = {
|
||||||
|
internalIndex = it
|
||||||
|
onSelectionChanged(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(modifier = modifier, contentAlignment = Alignment.Center) {
|
LaunchedEffect(lazyListState, onSelectionChanged) {
|
||||||
|
snapshotFlow { lazyListState.firstVisibleItemScrollOffset }
|
||||||
|
.map { calculateSnappedItemIndex(lazyListState) }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.drop(1)
|
||||||
|
.collectLatest {
|
||||||
|
haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove)
|
||||||
|
internalOnSelectionChanged(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = modifier
|
||||||
|
.height(size.height)
|
||||||
|
.width(size.width),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
) {
|
||||||
backgroundContent?.invoke(size)
|
backgroundContent?.invoke(size)
|
||||||
Row {
|
|
||||||
val singularPickerSize = DpSize(
|
|
||||||
width = size.width / 3,
|
|
||||||
height = size.height,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Day
|
var showManualInput by remember { mutableStateOf(false) }
|
||||||
val dayOfMonths = remember(internalSelection, minDate, maxDate) {
|
if (showManualInput) {
|
||||||
if (minDate == null && maxDate == null) {
|
var value by remember {
|
||||||
1..internalSelection.lengthOfMonth()
|
val currentString = items[internalIndex].toString()
|
||||||
} else {
|
mutableStateOf(TextFieldValue(text = currentString, selection = TextRange(currentString.length)))
|
||||||
val minDay = if (minDate?.month == internalSelection.month &&
|
|
||||||
minDate?.year == internalSelection.year
|
|
||||||
) {
|
|
||||||
minDate.dayOfMonth
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
val maxDay = if (maxDate?.month == internalSelection.month &&
|
|
||||||
maxDate?.year == internalSelection.year
|
|
||||||
) {
|
|
||||||
maxDate.dayOfMonth
|
|
||||||
} else {
|
|
||||||
31
|
|
||||||
}
|
|
||||||
minDay..maxDay.coerceAtMost(internalSelection.lengthOfMonth())
|
|
||||||
}.toList()
|
|
||||||
}
|
}
|
||||||
WheelTextPicker(
|
|
||||||
size = singularPickerSize,
|
|
||||||
texts = dayOfMonths.map { it.toString() },
|
|
||||||
backgroundContent = null,
|
|
||||||
startIndex = dayOfMonths.indexOfFirst { it == startDate.dayOfMonth }.coerceAtLeast(0),
|
|
||||||
onSelectionChanged = { index ->
|
|
||||||
val newDayOfMonth = dayOfMonths[index]
|
|
||||||
internalOnSelectionChange(internalSelection.withDayOfMonth(newDayOfMonth))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// Month
|
val scope = rememberCoroutineScope()
|
||||||
val months = remember(internalSelection, minDate, maxDate) {
|
BasicTextField(
|
||||||
val monthRange = if (minDate == null && maxDate == null) {
|
modifier = Modifier
|
||||||
1..12
|
.align(Alignment.Center)
|
||||||
} else {
|
.showSoftKeyboard(true)
|
||||||
val minMonth = if (minDate?.year == internalSelection.year) {
|
.clearFocusOnSoftKeyboardHide {
|
||||||
minDate.monthValue
|
scope.launch {
|
||||||
} else {
|
items
|
||||||
1
|
.indexOfFirst { it.toString() == value.text }
|
||||||
|
.takeIf { it >= 0 }
|
||||||
|
?.apply {
|
||||||
|
internalOnSelectionChanged(this)
|
||||||
|
lazyListState.scrollToItem(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
showManualInput = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value = value,
|
||||||
|
onValueChange = { value = it },
|
||||||
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
keyboardType = manualInputType!!,
|
||||||
|
imeAction = ImeAction.Done,
|
||||||
|
),
|
||||||
|
textStyle = MaterialTheme.typography.titleMedium +
|
||||||
|
TextStyle(
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
),
|
||||||
|
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.let {
|
||||||
|
if (manualInputType != null) {
|
||||||
|
it.clickableNoIndication { showManualInput = true }
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
},
|
||||||
|
state = lazyListState,
|
||||||
|
contentPadding = PaddingValues(vertical = size.height / RowCount * ((RowCount - 1) / 2)),
|
||||||
|
flingBehavior = rememberSnapFlingBehavior(lazyListState = lazyListState),
|
||||||
|
) {
|
||||||
|
itemsIndexed(items) { index, item ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(size.height / RowCount)
|
||||||
|
.width(size.width)
|
||||||
|
.alpha(
|
||||||
|
calculateAnimatedAlpha(
|
||||||
|
lazyListState = lazyListState,
|
||||||
|
index = index,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
) {
|
||||||
|
itemContent(item)
|
||||||
}
|
}
|
||||||
val maxMonth = if (maxDate?.year == internalSelection.year) {
|
|
||||||
maxDate.monthValue
|
|
||||||
} else {
|
|
||||||
12
|
|
||||||
}
|
|
||||||
minMonth..maxMonth
|
|
||||||
}
|
}
|
||||||
val dateFormatSymbols = DateFormatSymbols()
|
|
||||||
monthRange.map { it to dateFormatSymbols.months[it - 1] }
|
|
||||||
}
|
}
|
||||||
WheelTextPicker(
|
|
||||||
size = singularPickerSize,
|
|
||||||
texts = months.map { it.second },
|
|
||||||
backgroundContent = null,
|
|
||||||
startIndex = months.indexOfFirst { it.first == startDate.monthValue }.coerceAtLeast(0),
|
|
||||||
onSelectionChanged = { index ->
|
|
||||||
val newMonth = months[index].first
|
|
||||||
internalOnSelectionChange(internalSelection.withMonth(newMonth))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// Year
|
|
||||||
val years = remember(minDate, maxDate) {
|
|
||||||
val minYear = minDate?.year?.coerceAtLeast(1900) ?: 1900
|
|
||||||
val maxYear = maxDate?.year?.coerceAtMost(2100) ?: 2100
|
|
||||||
val yearRange = minYear..maxYear
|
|
||||||
yearRange.toList()
|
|
||||||
}
|
|
||||||
WheelTextPicker(
|
|
||||||
size = singularPickerSize,
|
|
||||||
texts = years.map { it.toString() },
|
|
||||||
backgroundContent = null,
|
|
||||||
startIndex = years.indexOfFirst { it == startDate.year }.coerceAtLeast(0),
|
|
||||||
onSelectionChanged = { index ->
|
|
||||||
val newYear = years[index]
|
|
||||||
internalOnSelectionChange(internalSelection.withYear(newYear))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,9 @@ fun Modifier.showSoftKeyboard(show: Boolean): Modifier = if (show) {
|
||||||
* For TextField, this modifier will clear focus when soft
|
* For TextField, this modifier will clear focus when soft
|
||||||
* keyboard is hidden.
|
* keyboard is hidden.
|
||||||
*/
|
*/
|
||||||
fun Modifier.clearFocusOnSoftKeyboardHide(): Modifier = composed {
|
fun Modifier.clearFocusOnSoftKeyboardHide(
|
||||||
|
onFocusCleared: (() -> Unit)? = null,
|
||||||
|
): Modifier = composed {
|
||||||
var isFocused by remember { mutableStateOf(false) }
|
var isFocused by remember { mutableStateOf(false) }
|
||||||
var keyboardShowedSinceFocused by remember { mutableStateOf(false) }
|
var keyboardShowedSinceFocused by remember { mutableStateOf(false) }
|
||||||
if (isFocused) {
|
if (isFocused) {
|
||||||
|
@ -100,6 +102,7 @@ fun Modifier.clearFocusOnSoftKeyboardHide(): Modifier = composed {
|
||||||
keyboardShowedSinceFocused = true
|
keyboardShowedSinceFocused = true
|
||||||
} else if (keyboardShowedSinceFocused) {
|
} else if (keyboardShowedSinceFocused) {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
|
onFocusCleared?.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue