Как переместить курсор в конец TextField после поворота экрана или изменения системной темы и сохранить отображение клавиатуры?
У меня есть экран сTextfield
как панель поиска, которая автоматически фокусируется при первом отображении экрана. Проблема в том, что послеscreen rotation
илиsystem theme change
(темный режим/светлый режим),cursor
перемещается в начало TextField, даже если значение TextField не пусто и клавиатура закрывается. Помогите пожалуйста, два дня ищу. Некоторые примеры кода:
Версия компоновки: 1.3.0 Материал 3: 1.0.0
ПоискBookScreen.kt
val myViewModel = SearchBookViewModel()
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SearchBookScreen(
modifier: Modifier = Modifier,
navController: NavController,
viewModel: SearchBookViewModel = myViewModel,
filters: Map<SearchFilterType, FilterOptions> = FILTERS
) {
val focusRequester = remember { FocusRequester() }
val searchInputValue = viewModel.searchInputValue.value
val filtersState = viewModel.filtersState
LaunchedEffect(Unit) { this.coroutineContext.job.invokeOnCompletion { focusRequester.requestFocus() } }
Scaffold(
topBar = {
Column {
TextField(
singleLine = true,
placeholder = {
Text(text = stringResource(id = R.string.search_bar))
},
value = searchInputValue.text,
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester)
,
onValueChange = {
viewModel.onEvent(SearchBookEvent.EnteredSearchValue(it))
},
leadingIcon = {
IconButton(onClick = {
viewModel.onEvent(SearchBookEvent.ClearSearchInput)
navController.navigateUp()
}
) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "Go back"
)
}
},
colors = TextFieldDefaults.textFieldColors(
unfocusedIndicatorColor = Color.Transparent,
focusedIndicatorColor = Color.Transparent
),
trailingIcon = {
IconButton(onClick = { viewModel.onEvent(SearchBookEvent.ClearSearchInput) }) {
Icon(imageVector = Icons.Default.Clear, contentDescription = "clear")
}
},
)
SearchBookViewModel.kt
class SearchBookViewModel: ViewModel() {
private val _searchInputValue = mutableStateOf(TextFieldValue("", selection = TextRange.Zero))
val searchInputValue: State<TextFieldValue> = _searchInputValue
fun onEvent(event: SearchBookEvent) {
when (event) {
is SearchBookEvent.EnteredSearchValue -> {
_searchInputValue.value = searchInputValue.value.copy(text = event.value, selection = TextRange(event.value.length))
}
}
}
1 ответ
Для выбора, вопрос здесь,
value = searchInputValue.text
вы манипулируете текстом, используя, но вы просто обновляете параметр значения, используя обычныеString
(текстовое свойство TextFieldValue), все, что вы делаете сTextFieldValue
экземпляр не отражает ваш .
Я внес некоторые изменения в ваш код, используяState<TextFieldValue>'s
делегировать
val searchInputValue by viewModel.searchInputValue
и использовал его как фактическое значение вместо егоtext
свойство для вашего нравится это.
value = searchInputValue
Однако вам нужно изменить способ его обновления, поэтому я изменяюonValueChange
также, я только использовал.text
так как я не хочу вносить изменения в другие части и оставлять это на ваше усмотрение.
onValueChange = {
viewModel.onEvent(SearchBookEvent.EnteredSearchValue(it.text))
}
ТвойTextField
реализация должна выглядеть так
TextField(
singleLine = true,
placeholder = {
Text(text = "Type Here")
},
value = searchInputValue, // <- notice this
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester),
onValueChange = {
viewModel.onEvent(SearchBookEvent.EnteredSearchValue(it.text)) // <- and this
}
Примените все эти изменения, и при переключении режима темы курсор/выделение останется в конце.
Теперь о проблеме с клавиатурой, показывающей ее изначально, мне пришлось реализовать что-то из этого поста , добавив задержку перед запросом фокуса,
LaunchedEffect(Unit) {
delay(200)
focusRequester.requestFocus()
}
и чтобы сохранить клавиатуру при изменении режима темы, мне пришлось указать это в своей деятельности.
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED)