Flutter Material3中Search Anchor返回时断言失败问题求助
解决Flutter Material3 SearchAnchor断言错误:
_anchor != null 问题原因
这个断言错误本质是SearchAnchor内部状态不一致导致的:当组件因searchController文本变化重建、或hot reload时,SearchAnchor的内部锚点实例(_anchor)尚未完成初始化,就触发了依赖该实例的操作;另外,焦点管理不当、Controller生命周期未正确处理也会加剧这个状态异常。
解决方案
1. 规范SearchController与FocusNode的生命周期
在State类中初始化并销毁Controller和FocusNode,避免重建时复用无效实例:
class _YourPageState extends State<YourPage> { late final SearchController searchController; late final FocusNode searchFocusNode; final GlobalKey<SearchAnchorState> _searchAnchorKey = GlobalKey(); // 新增SearchAnchor的Key @override void initState() { super.initState(); searchController = SearchController(); searchFocusNode = FocusNode(); } @override void dispose() { searchController.dispose(); searchFocusNode.dispose(); super.dispose(); } // ... 其他代码 }
2. 修正View返回按钮的逻辑
移除创建临时FocusNode的操作,改为直接取消焦点,再关闭搜索视图,避免干扰SearchAnchor的内部状态:
viewLeading: IconButton( onPressed: () { // 先取消焦点,再关闭视图 searchFocusNode.unfocus(); searchController.closeView(""); }, icon: const Icon(Icons.arrow_back)),
3. 给SearchAnchor添加GlobalKey
确保组件重建时,SearchAnchor的状态被正确保留,避免内部_anchor实例丢失:
SearchAnchor( key: _searchAnchorKey, // 新增这一行 viewLeading: ..., // 其他原有代码 // ... 其他参数 )
4. 简化SearchBar的onTap逻辑
openView后SearchAnchor会自动处理焦点,无需手动请求,避免重复操作导致状态冲突:
onTap: () { searchController.openView(); // 移除这一行:FocusScope.of(context).requestFocus(focusNode); },
修改后的完整代码片段
class _YourPageState extends State<YourPage> { late final SearchController searchController; late final FocusNode searchFocusNode; final GlobalKey<SearchAnchorState> _searchAnchorKey = GlobalKey(); final GlobalKey _searchBarKey = GlobalKey(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey(); double height = 0; double width = 0; Color textFieldBackgoundColor = Colors.grey[100]!; @override void initState() { super.initState(); searchController = SearchController(); searchFocusNode = FocusNode(); } @override void dispose() { searchController.dispose(); searchFocusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { height = MediaQuery.of(context).size.height; width = MediaQuery.of(context).size.width; return Scaffold( key: _scaffoldKey, body: SearchAnchor( key: _searchAnchorKey, viewLeading: IconButton( onPressed: () { searchFocusNode.unfocus(); searchController.closeView(""); }, icon: const Icon(Icons.arrow_back)), searchController: searchController, isFullScreen: true, builder: (BuildContext context, SearchController controller) { return SearchBar( key: _searchBarKey, padding: const MaterialStatePropertyAll<EdgeInsets>( EdgeInsets.only(left: 8.0, right: 8.0), ), hintText: "Search your notes", hintStyle: const MaterialStatePropertyAll(TextStyle( fontSize: 16, fontWeight: FontWeight.normal, color: Colors.black54)), leading: IconButton( icon: const Icon(Icons.menu), onPressed: () { _scaffoldKey.currentState!.openDrawer(); }, ), focusNode: searchFocusNode, shape: MaterialStatePropertyAll(RoundedRectangleBorder( borderRadius: BorderRadius.circular(50))), controller: controller, onTap: () { controller.openView(); }, trailing: [], ); }, viewBuilder: (suggestions) { return Container( height: height, width: width, color: textFieldBackgoundColor, child: const Center(child: Icon(Icons.mood, color: Colors.black)), ); }, suggestionsBuilder: (BuildContext context, SearchController controller) { return <Widget>[const Icon(Icons.abc)]; }, ), ); } }
额外提示
如果上述方案仍未解决,可尝试升级Flutter SDK到最新稳定版——这个_anchor != null的断言错误曾在部分老版本的Material3组件中存在,官方后续已修复相关状态同步问题。
内容的提问来源于stack exchange,提问作者Priyanshu Paliwal
相关产品推荐
相关产品推荐

