Flutter RawAutocomplete的OptionsViewBuilder无法显示SnackBar求助
问题解决:RawAutocomplete中SnackBar无法弹出的问题
问题原因
RawAutocomplete的optionsViewBuilder返回的选项列表是渲染在Overlay中的,它的上下文属于独立的Widget分支,和页面的Scaffold不在同一个上下文树中。即使你在itemBuilder里添加了Builder,也无法获取到Scaffold的上下文,因此会报错Scaffold.of() called with a context that does not contain a Scaffold。
解决方案
方案1:使用GlobalKey直接获取ScaffoldState
这是最直接的解决方式,通过全局Key绕过上下文查找的限制:
- 在页面的State类中定义全局Key:
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
- 给页面的Scaffold设置这个Key:
Scaffold( key: _scaffoldKey, // 页面其他内容 )
- 修改点击事件中的代码,用全局Key调用SnackBar:
onTap: () { refreshList( context, operation: 'add', option, ); // 显示SnackBar _scaffoldKey.currentState?.showSnackBar( SnackBar(content: Text('已选择${option.name}')), ); },
方案2:利用RawAutocomplete的onSelected回调(推荐)
RawAutocomplete本身提供了onSelected参数,它的上下文属于页面主Widget树,可以直接访问Scaffold,更符合Flutter的设计规范:
- 给RawAutocomplete添加
onSelected回调:
RawAutocomplete<Product>( onSelected: (Product selectedProduct) { refreshList( context, operation: 'add', selectedProduct, ); // 这里的context可直接获取Scaffold ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('已选择${_displayStringForOption(selectedProduct)}')), ); }, // 原有参数保持不变 )
- 修改optionsViewBuilder中的GestureDetector,调用传入的
onSelected:
optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<Product> onSelected, Iterable<Product> options) { return Align( alignment: Alignment.topLeft, child: Material( elevation: 4.0, child: SizedBox( height: 200.0, child: ListView.builder( padding: const EdgeInsets.all(8.0), itemCount: options.length, itemBuilder: (BuildContext context, int index) { final Product option = options.elementAt(index); return GestureDetector( onTap: () { onSelected(option); // 调用全局的onSelected逻辑 }, child: ListTile( title: Text(_displayStringForOption(option) + " Price Kes. ${option.price}"), leading: Image.network( "http://192.168.1.38/ci/uploads/${option.image}", errorBuilder: (context, error, stackTrace) { return Image.asset("assets/images/camera.png"); }, ), ), ); }, ), ), ), ); },
提示:可以去掉原来itemBuilder里的
Builder,因为不再需要它来获取上下文。
额外说明
- Flutter 2.0+版本推荐使用
ScaffoldMessenger.of(context)代替Scaffold.of(context).showSnackBar,后者已被标记为过时。 - 如果你的
refreshList函数需要使用Scaffold上下文,确保传递的是页面主上下文(比如方案2中使用的context)。
内容的提问来源于stack exchange,提问作者theKD
相关产品推荐
相关产品推荐

