未在颤振自定义应用程序栏中获取脚手架上下文

Posted

技术标签:

【中文标题】未在颤振自定义应用程序栏中获取脚手架上下文【英文标题】:Not getting the scaffold context in flutter custom app bar 【发布时间】:2021-09-02 13:43:14 【问题描述】:

我已经编写了这个颤振小部件,我想实现一个自定义应用栏和一个抽屉。这是我的起始小部件

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Food App',
        theme: ThemeData(
          primaryColor: kPrimaryColor,
          scaffoldBackgroundColor: Colors.white,
        ),
        home: Scaffold(
          bottomNavigationBar: BottomNavBar(),
          body: HomeScreen(),
          drawer: CustomDrawer(),
          appBar: homeAppBar(context, (context) 
            Scaffold.of(context).openDrawer();
          ),
        ));
  

我已经在应用栏图标按钮中实现了回调

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:food_app/constants.dart';

AppBar homeAppBar(BuildContext context, Function function) 
  return AppBar(
    backgroundColor: Colors.white,
    elevation: 0,
    leading: IconButton(
      icon: SvgPicture.asset("assets/icons/menu.svg"),
      onPressed: () 
        function(context);
      ,
    ),
    title: RichText(
      text: TextSpan(
        style: Theme.of(context)
            .textTheme
            .headline6
            .copyWith(fontWeight: FontWeight.bold),
        children: [
          TextSpan(
            text: "Makana",
            style: TextStyle(color: ksecondaryColor),
          ),
          TextSpan(
            text: "Food",
            style: TextStyle(color: kPrimaryColor),
          ),
        ],
      ),
    ),
    actions: <Widget>[
      IconButton(
        icon: SvgPicture.asset("assets/icons/notification.svg"),
        onPressed: () ,
      ),
    ],
  );

它给了我一个错误

════════ Exception caught by gesture ═══════════════════════════════════════════
The following assertion was thrown while handling a gesture:
Scaffold.of() called with a context that does not contain a Scaffold.

No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This usually happens when the context provided is from the same StatefulWidget as that whose build function actually creates the Scaffold widget being sought.

There are several ways to avoid this problem. The simplest is to use a Builder to get a context that is "under" the Scaffold. For an example of this, please see the documentation for Scaffold.of():
  https://api.flutter.dev/flutter/material/Scaffold/of.html
A more efficient solution is to split your build function into several widgets. This introduces a new context from which you can obtain the Scaffold. In this solution, you would have an outer widget that creates the Scaffold populated by instances of your new inner widgets, and then in these inner widgets you would use Scaffold.of().
A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, then use the key.currentState property to obtain the ScaffoldState rather than using the Scaffold.of() function.

The context used was: MyApp
When the exception was thrown, this was the stack

我也试过这样

AppBar homeAppBar(BuildContext context) 
  return AppBar(
    backgroundColor: Colors.white,
    elevation: 0,
    leading: IconButton(
      icon: SvgPicture.asset("assets/icons/menu.svg"),
      onPressed: () 
        Scaffold.of(context).openDrawer();
      ,
    ),
    title: RichText(
      text: TextSpan(
        style: Theme.of(context)
            .textTheme
            .headline6
            .copyWith(fontWeight: FontWeight.bold),
        children: [
          TextSpan(
            text: "Makana",
            style: TextStyle(color: ksecondaryColor),
          ),
          TextSpan(
            text: "Food",
            style: TextStyle(color: kPrimaryColor),
          ),
        ],
      ),
    ),
    actions: <Widget>[
      IconButton(
        icon: SvgPicture.asset("assets/icons/notification.svg"),
        onPressed: () ,
      ),
    ],
  );

虽然它位于 main.dart 的脚手架下,但它仍然会抛出相同的错误。我在应用栏中尝试了 Builder,但在 AppBar 返回类型中是不可接受的。我是进入扑动世界的新蜜蜂。请帮忙!

【问题讨论】:

【参考方案1】:

问题在于您传递给homeAppBar 函数的上下文无权访问Scaffold。

  @override
// The following context that is the one that you are passing to the function is above the scaffold and hence does not finds any scaffold "above" it.
  Widget build(BuildContext context) 
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Food App',
        theme: ThemeData(
          primaryColor: kPrimaryColor,
          scaffoldBackgroundColor: Colors.white,
        ),
        home: Scaffold(
          bottomNavigationBar: BottomNavBar(),
          body: HomeScreen(),
          drawer: CustomDrawer(),
          appBar: homeAppBar(context, (context) 

有两种解决方案,或者将homeAppBar 包装在 Builder 中,如下所示:

Builder(builder: (ctx)=>homeAppBar(ctx),)

或者只是不使用函数重构小部件来使用一个类,这是我出于优化原因推荐的类,请参阅this answer 以获得详细说明。

【讨论】:

谢谢,帮了大忙! Builder(builder: (ctx)=>homeAppBar(ctx),) 不适用于 PreferredSizedWidget。 检查here。我们的想法是将您的 appbar 提取到另一个类,并在 MyApp 中调用包装在 PreferredSize 中的新小部件。

以上是关于未在颤振自定义应用程序栏中获取脚手架上下文的主要内容,如果未能解决你的问题,请参考以下文章

AssetImage 未在颤振应用程序中显示图像

Codemagic 未在 Appstore Connect 中卸载颤振应用程序集

颤振导航未定义的“上下文”

颤振推送通知图像未在所有设备上显示

在颤振中如何清除栏中的通知?

未在自定义 UISearchBar 中获取过滤器数据