Use TextFieldState in BasicTextField where applicable (#1201)

Co-authored-by: p
This commit is contained in:
AntsyLich 2024-09-07 14:11:14 +06:00 committed by GitHub
parent c4f235ae07
commit bec549cc44
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 38 additions and 45 deletions

View file

@ -13,8 +13,10 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.clearText
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Close import androidx.compose.material.icons.outlined.Close
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
@ -28,11 +30,8 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.NonRestartableComposable import androidx.compose.runtime.NonRestartableComposable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
@ -43,7 +42,6 @@ import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -88,7 +86,7 @@ class SettingsSearchScreen : Screen() {
focusRequester.requestFocus() focusRequester.requestFocus()
} }
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue()) } val textFieldState = rememberTextFieldState()
Scaffold( Scaffold(
topBar = { topBar = {
Column { Column {
@ -103,20 +101,19 @@ class SettingsSearchScreen : Screen() {
}, },
title = { title = {
BasicTextField( BasicTextField(
value = textFieldValue, state = textFieldState,
onValueChange = { textFieldValue = it },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.focusRequester(focusRequester) .focusRequester(focusRequester)
.runOnEnterKeyPressed(action = focusManager::clearFocus), .runOnEnterKeyPressed(action = focusManager::clearFocus),
textStyle = MaterialTheme.typography.bodyLarge textStyle = MaterialTheme.typography.bodyLarge
.copy(color = MaterialTheme.colorScheme.onSurface), .copy(color = MaterialTheme.colorScheme.onSurface),
singleLine = true, lineLimits = TextFieldLineLimits.SingleLine,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = KeyboardActions(onSearch = { focusManager.clearFocus() }), onKeyboardAction = { focusManager.clearFocus() },
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary), cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
decorationBox = { decorator = {
if (textFieldValue.text.isEmpty()) { if (textFieldState.text.isEmpty()) {
Text( Text(
text = stringResource(MR.strings.action_search_settings), text = stringResource(MR.strings.action_search_settings),
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
@ -128,8 +125,8 @@ class SettingsSearchScreen : Screen() {
) )
}, },
actions = { actions = {
if (textFieldValue.text.isNotEmpty()) { if (textFieldState.text.isNotEmpty()) {
IconButton(onClick = { textFieldValue = TextFieldValue() }) { IconButton(onClick = { textFieldState.clearText() }) {
Icon( Icon(
imageVector = Icons.Outlined.Close, imageVector = Icons.Outlined.Close,
contentDescription = null, contentDescription = null,
@ -144,7 +141,7 @@ class SettingsSearchScreen : Screen() {
}, },
) { contentPadding -> ) { contentPadding ->
SearchResult( SearchResult(
searchKey = textFieldValue.text, searchKey = textFieldState.text.toString(),
listState = listState, listState = listState,
contentPadding = contentPadding, contentPadding = contentPadding,
) { result -> ) { result ->

View file

@ -25,8 +25,10 @@ import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.text.input.clearText
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.CheckCircle
@ -59,7 +61,6 @@ import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.capitalize import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.toLowerCase import androidx.compose.ui.text.toLowerCase
@ -84,8 +85,7 @@ import tachiyomi.presentation.core.util.secondaryItemAlpha
@Composable @Composable
fun TrackerSearch( fun TrackerSearch(
query: TextFieldValue, state: TextFieldState,
onQueryChange: (TextFieldValue) -> Unit,
onDispatchQuery: () -> Unit, onDispatchQuery: () -> Unit,
queryResult: Result<List<TrackSearch>>?, queryResult: Result<List<TrackSearch>>?,
selected: TrackSearch?, selected: TrackSearch?,
@ -115,20 +115,19 @@ fun TrackerSearch(
}, },
title = { title = {
BasicTextField( BasicTextField(
value = query, state = state,
onValueChange = onQueryChange,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.focusRequester(focusRequester) .focusRequester(focusRequester)
.runOnEnterKeyPressed(action = dispatchQueryAndClearFocus), .runOnEnterKeyPressed(action = dispatchQueryAndClearFocus),
textStyle = MaterialTheme.typography.bodyLarge textStyle = MaterialTheme.typography.bodyLarge
.copy(color = MaterialTheme.colorScheme.onSurface), .copy(color = MaterialTheme.colorScheme.onSurface),
singleLine = true, lineLimits = TextFieldLineLimits.SingleLine,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = KeyboardActions(onSearch = { dispatchQueryAndClearFocus() }), onKeyboardAction = { dispatchQueryAndClearFocus() },
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary), cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
decorationBox = { decorator = {
if (query.text.isEmpty()) { if (state.text.isEmpty()) {
Text( Text(
text = stringResource(MR.strings.action_search_hint), text = stringResource(MR.strings.action_search_hint),
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
@ -140,10 +139,10 @@ fun TrackerSearch(
) )
}, },
actions = { actions = {
if (query.text.isNotEmpty()) { if (state.text.isNotEmpty()) {
IconButton( IconButton(
onClick = { onClick = {
onQueryChange(TextFieldValue()) state.clearText()
focusRequester.requestFocus() focusRequester.requestFocus()
}, },
) { ) {

View file

@ -1,7 +1,7 @@
package eu.kanade.presentation.track package eu.kanade.presentation.track
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
@ -13,8 +13,7 @@ internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composab
private val fullPageWithSecondSelected = @Composable { private val fullPageWithSecondSelected = @Composable {
val items = someTrackSearches().take(30).toList() val items = someTrackSearches().take(30).toList()
TrackerSearch( TrackerSearch(
query = TextFieldValue(text = "search text"), state = TextFieldState(initialText = "search text"),
onQueryChange = {},
onDispatchQuery = {}, onDispatchQuery = {},
queryResult = Result.success(items), queryResult = Result.success(items),
selected = items[1], selected = items[1],
@ -25,8 +24,7 @@ internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composab
} }
private val fullPageWithoutSelected = @Composable { private val fullPageWithoutSelected = @Composable {
TrackerSearch( TrackerSearch(
query = TextFieldValue(text = ""), state = TextFieldState(),
onQueryChange = {},
onDispatchQuery = {}, onDispatchQuery = {},
queryResult = Result.success(someTrackSearches().take(30).toList()), queryResult = Result.success(someTrackSearches().take(30).toList()),
selected = null, selected = null,
@ -37,8 +35,7 @@ internal class TrackerSearchPreviewProvider : PreviewParameterProvider<@Composab
} }
private val loading = @Composable { private val loading = @Composable {
TrackerSearch( TrackerSearch(
query = TextFieldValue(), state = TextFieldState(),
onQueryChange = {},
onDispatchQuery = {}, onDispatchQuery = {},
queryResult = null, queryResult = null,
selected = null, selected = null,

View file

@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
@ -28,7 +29,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
@ -666,11 +666,10 @@ data class TrackerSearchScreen(
val state by screenModel.state.collectAsState() val state by screenModel.state.collectAsState()
var textFieldValue by remember { mutableStateOf(TextFieldValue(initialQuery)) } val textFieldState = rememberTextFieldState(initialQuery)
TrackerSearch( TrackerSearch(
query = textFieldValue, state = textFieldState,
onQueryChange = { textFieldValue = it }, onDispatchQuery = { screenModel.trackingSearch(textFieldState.text.toString()) },
onDispatchQuery = { screenModel.trackingSearch(textFieldValue.text) },
queryResult = state.queryResult, queryResult = state.queryResult,
selected = state.selected, selected = state.selected,
onSelectedChange = screenModel::updateSelection, onSelectedChange = screenModel::updateSelection,

View file

@ -16,6 +16,8 @@ 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.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.TextFieldState
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
@ -25,6 +27,7 @@ import androidx.compose.runtime.mutableIntStateOf
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.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
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
@ -37,7 +40,6 @@ import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType 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.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
@ -141,9 +143,9 @@ private fun <T> WheelPicker(
var showManualInput by remember { mutableStateOf(false) } var showManualInput by remember { mutableStateOf(false) }
if (showManualInput) { if (showManualInput) {
var value by remember { val value = rememberSaveable(saver = TextFieldState.Saver) {
val currentString = items[internalIndex].toString() val currentString = items[internalIndex].toString()
mutableStateOf(TextFieldValue(text = currentString, selection = TextRange(currentString.length))) TextFieldState(initialText = currentString, initialSelection = TextRange(currentString.length))
} }
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
@ -164,9 +166,8 @@ private fun <T> WheelPicker(
showManualInput = false showManualInput = false
} }
}, },
value = value, state = value,
onValueChange = { value = it }, lineLimits = TextFieldLineLimits.SingleLine,
singleLine = true,
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
keyboardType = manualInputType!!, keyboardType = manualInputType!!,
imeAction = ImeAction.Done, imeAction = ImeAction.Done,