You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AnimatedVisibility时遇FocusRequester未初始化错误求助

问题描述

我想实现点击按钮后打开搜索框并唤起键盘的功能,效果分为两种状态:

  • 初始状态:显示搜索图标按钮
  • 点击后:显示搜索输入框,隐藏按钮并唤起键盘

但使用AnimatedVisibility控制显隐时出现以下错误:

FocusRequester is not initialized. Here are some possible fixes:

  1. Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
  2. Did you forget to add a Modifier.focusRequester() ?
  3. 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未绑定。按以下步骤修复:

  1. 正确声明并绑定FocusRequester

    • 在TopAppBar的actions作用域内声明FocusRequester,用remember持久化,确保它在AnimatedVisibility外部。
    • 给TextField添加Modifier.focusRequester(focusRequester)。
  2. 用LaunchedEffect在搜索框显示后请求焦点

    • 监听搜索激活状态,当状态变为true时,在LaunchedEffect中执行焦点请求和键盘唤起,确保搜索框已完成组合。
  3. 简化互斥状态

    • 两个显隐变量是互斥的,合并为一个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:40:27