使用AnimatedVisibility时遇FocusRequester未初始化错误求助
问题描述
我想实现点击按钮后打开搜索框并唤起键盘的功能,效果分为两种状态:
- 初始状态:显示搜索图标按钮
- 点击后:显示搜索输入框,隐藏按钮并唤起键盘
但使用AnimatedVisibility控制显隐时出现以下错误:
FocusRequester is not initialized. Here are some possible fixes:
- Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
- Did you forget to add a Modifier.focusRequester() ?
- Are you attempting to request focus during composition? Focus requests should be made in
response to some event. Eg Modifier.clickable { focusRequester.requestFocus() }
不使用AnimatedVisibility时功能完全正常,推测是组件更新不及时导致光标无法定位,但不知道如何解决。我的代码如下:
topBar = { TopAppBar( actions = { // val keyboardController = LocalSoftwareKeyboardController.current //val focusRequester = remember { FocusRequester() } var visibleSearchBar by remember { mutableStateOf(false) } var visiblecurrentSearch by remember { mutableStateOf(true) } val state = remember { mutableStateOf(TextFieldValue("")) } AnimatedVisibility(visible = visiblecurrentSearch) { IconButton(onClick = { visibleSearchBar = true visiblecurrentSearch = false //focusRequester.requestFocus() //keyboardController?.show() }) { Icon(painter = painterResource(id = R.drawable.ic_baseline_search_24), contentDescription = "search") } } AnimatedVisibility(visible = visibleSearchBar) { TextField( value = state.value, onValueChange = { value -> state.value = value }, enabled = true, shape = RoundedCornerShape(25.dp), modifier = Modifier //.focusRequester(focusRequester) .fillMaxWidth() .padding(end = 10.dp) .scale(scaleX = 1F, scaleY = 0.9F), textStyle = TextStyle(color = Color.Black), placeholder = { Text( text = "Search", fontSize = 14.sp, ) }, keyboardActions = KeyboardActions( onDone = { //movie = list } ), leadingIcon = { Icon( Icons.Default.Search, contentDescription = "", modifier = Modifier .size(20.dp) ) }, trailingIcon = { IconButton( onClick = { state.value = TextFieldValue("") visibleSearchBar = false visiblecurrentSearch = true } ) { Icon( Icons.Default.Close, contentDescription = "", modifier = Modifier .size(20.dp) ) } }, singleLine = true, colors = TextFieldDefaults.textFieldColors( textColor = Color.Black, cursorColor = Color.Black, leadingIconColor = Color.Black, trailingIconColor = Color.Black, focusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent, disabledIndicatorColor = Color.Black ) ) } }, title = { }, navigationIcon = { IconButton(onClick = {}) { Icon(painter = painterResource(id = R.drawable.ic_baseline_menu_24), contentDescription = "menu") } }, backgroundColor = Color.White, contentColor = Color.Black, elevation = 3.dp ) }
解决方案
问题核心是AnimatedVisibility会延迟搜索框的组合时机,直接在按钮点击事件中请求焦点时,搜索框还未完成初始化,导致FocusRequester未绑定。按以下步骤修复:
正确声明并绑定FocusRequester
- 在
TopAppBar的actions作用域内声明FocusRequester,用remember持久化,确保它在AnimatedVisibility外部。 - 给
TextField添加Modifier.focusRequester(focusRequester)。
- 在
用LaunchedEffect在搜索框显示后请求焦点
- 监听搜索激活状态,当状态变为
true时,在LaunchedEffect中执行焦点请求和键盘唤起,确保搜索框已完成组合。
- 监听搜索激活状态,当状态变为
简化互斥状态
- 两个显隐变量是互斥的,合并为一个
isSearchActive变量,避免状态同步问题。
- 两个显隐变量是互斥的,合并为一个
修复后的完整代码:
topBar = { TopAppBar( actions = { val keyboardController = LocalSoftwareKeyboardController.current val focusRequester = remember { FocusRequester() } var isSearchActive by remember { mutableStateOf(false) } val searchText = remember { mutableStateOf(TextFieldValue("")) } // 搜索按钮 AnimatedVisibility(visible = !isSearchActive) { IconButton(onClick = { isSearchActive = true }) { Icon( painter = painterResource(id = R.drawable.ic_baseline_search_24), contentDescription = "search" ) } } // 搜索输入框 AnimatedVisibility(visible = isSearchActive) { TextField( value = searchText.value, onValueChange = { searchText.value = it }, enabled = true, shape = RoundedCornerShape(25.dp), modifier = Modifier .focusRequester(focusRequester) .fillMaxWidth() .padding(end = 10.dp) .scale(scaleX = 1F, scaleY = 0.9F), textStyle = TextStyle(color = Color.Black), placeholder = { Text( text = "Search", fontSize = 14.sp, ) }, keyboardActions = KeyboardActions( onDone = { // 处理搜索逻辑 } ), leadingIcon = { Icon( Icons.Default.Search, contentDescription = "", modifier = Modifier.size(20.dp) ) }, trailingIcon = { IconButton( onClick = { searchText.value = TextFieldValue("") isSearchActive = false keyboardController?.hide() } ) { Icon( Icons.Default.Close, contentDescription = "", modifier = Modifier.size(20.dp) ) } }, singleLine = true, colors = TextFieldDefaults.textFieldColors( textColor = Color.Black, cursorColor = Color.Black, leadingIconColor = Color.Black, trailingIconColor = Color.Black, focusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent, disabledIndicatorColor = Color.Black ) ) } // 当搜索激活时,请求焦点并唤起键盘 LaunchedEffect(isSearchActive) { if (isSearchActive) { focusRequester.requestFocus() keyboardController?.show() } } }, title = {}, navigationIcon = { IconButton(onClick = {}) { Icon( painter = painterResource(id = R.drawable.ic_baseline_menu_24), contentDescription = "menu" ) } }, backgroundColor = Color.White, contentColor = Color.Black, elevation = 3.dp ) }
内容的提问来源于stack exchange,提问作者VangelNum
相关产品推荐
相关产品推荐

