Flutter子组件CustomAppBar调用方法打开抽屉报错如何解决
问题根因
你遇到的Scaffold.of() called with a context that does not contain a Scaffold报错,本质是调用Scaffold.of时传入的BuildContext,不在当前Scaffold的子树范围内:你HomePage中创建Scaffold的上下文,和你传入CustomAppBar、用来调用Scaffold.of的上下文是同一个,这个上下文对应的Widget是Scaffold的父节点,自然找不到子树里的Scaffold实例。
可行解决方法
方案1:使用GlobalKey绑定Scaffold(最稳定,推荐优先用)
直接在父页面HomePage中创建全局key绑定Scaffold,把操作抽屉的逻辑封装在父层,通过回调传给子组件,子组件不需要感知Scaffold的存在。
代码示例:
home_page.dart 改动
class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { // 定义绑定Scaffold的GlobalKey final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); @override Widget build(BuildContext context) { return Scaffold( // 把key赋值给Scaffold key: _scaffoldKey, drawer: const Drawer(), // 直接把操作方法作为回调传给CustomAppBar appBar: CustomAppBar( onBack: () => Navigator.pop(context), onOpenDrawer: () => _scaffoldKey.currentState?.openDrawer(), ), body: const SizedBox(), ); } }
appbar_widget.dart 改动
class CustomAppBar extends PreferredSizeWidget { // 定义回调参数,不需要传pFunction做类型判断 final VoidCallback? onBack; final VoidCallback? onOpenDrawer; const CustomAppBar({super.key, this.onBack, this.onOpenDrawer}); @override Widget build(BuildContext context) { return AppBar( leading: IconButton( icon: const Icon(Icons.menu), onPressed: () => onOpenDrawer?.call(), ), // 返回按钮逻辑同理 actions: [IconButton(icon: const Icon(Icons.arrow_back), onPressed: () => onBack?.call())], ); } }
方案2:用Builder包裹子组件获取正确上下文
如果你不想用GlobalKey,也可以在父层传入CustomAppBar时,用Builder组件生成一个位于Scaffold子树内的新上下文,就能正常调用Scaffold.of:
Scaffold( drawer: const Drawer(), appBar: Builder( // 这里的context是Scaffold子树内的上下文,可以找到Scaffold实例 builder: (context) => CustomAppBar( pFunction: (type) { if (type == 'openDrawer') { Scaffold.of(context).openDrawer(); } else if (type == 'back') { Navigator.pop(context); } } ), ), )
更优实现方案
推荐完全抛弃pFunction传类型判断的实现,改用回调透传的方式做组件解耦:
- CustomAppBar作为通用组件,只定义暴露必要的交互回调,不需要关心父页面的具体业务逻辑,不管父页面是要开抽屉还是跳页,都由父层自己实现回调逻辑
- 这种实现下CustomAppBar可以直接复用在其他页面,不需要修改内部代码适配不同页面的逻辑,后续维护成本更低
- 避免了上下文查找的问题,运行更稳定,出问题也只需要排查父层的回调逻辑即可
内容的提问来源于stack exchange,提问作者Kyrill
相关产品推荐
相关产品推荐

