MaterialApp构建错误:找不到Overlay小部件。

12

我在构建 NavigationDrawer 时遇到错误,其中 Tooltip 组件需要以 Material App 为祖先。

以下是错误的具体信息:

I/flutter ( 5780): _TooltipState#bc79e(ticker inactive)):
I/flutter ( 5780): No Overlay widget found.
I/flutter ( 5780): Tooltip widgets require an Overlay widget ancestor for correct operation.
I/flutter ( 5780): The most common way to add an Overlay to an application is to include a MaterialApp or Navigator
I/flutter ( 5780): widget in the runApp() call.
I/flutter ( 5780): The specific widget that failed to find an overlay was:
I/flutter ( 5780):   Tooltip
I/flutter ( 5780): 
I/flutter ( 5780): The relevant error-causing widget was:
I/flutter ( 5780):   AppBar

我的 main.dart 代码

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ... //basic info title & theme

      builder: (context, child) => LayoutTemplate(child: child),
      initialRoute:"/home",

      ... //Routing stuff like generate route & navigator key 
    );
  }
}

布局模板小部件

class LayoutTemplate extends StatelessWidget {
  final Widget child;

  const LayoutTemplate({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("home"))
        drawer: NavDrawer()
        body: Column(
          children: <Widget>[
            //NavigationBar(),
            Expanded(
              child: child,
            )
          ],
       ),
    );
  }
}

非常抱歉添加了太多代码。我不确定是什么原因导致问题。也许来自MaterialAppbuilder引起了问题。

感谢您的帮助。


1
请始终发布一个最小可重现的代码,以便我们可以在本地运行,否则我们怎么知道你的“sl”、“NavigationService”、“sizingInformation”、“Routes.clientList”等等是什么。你的代码几乎每一行都使用了项目中定义的字段,但你没有分享。你在SO上已经有将近6年的时间了,所以请发布一个最小可重现的代码,让其他人也能运行。 - iDecode
我已经尝试删除不必要的代码,请检查更新后的问题。 - akshay bhange
1
谢谢,您能修改 initialRouteonGenerateRoutenavigatorKey 吗? - iDecode
我使用的是TextField而不是Tooltip,遇到了非常类似的问题。你找到解决方案了吗?我猜我们在跟着同一个教程走! - pitazzo
4个回答

26

在您的构建器中,只需返回一个使用LayoutTemplate作为OverlayEntry的叠加小部件。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ... //basic info title & theme

      builder: (context, child) {
        return Overlay(
          initialEntries: [
            OverlayEntry(
              builder: (context) => LayoutTemplate(child: child),
            ),
          ],
        );
      },
      initialRoute:"/home",

      ... //Routing stuff like generate route & navigator key 
    );
  }
}

这解决了问题,谢谢。你能解释一下为什么需要Overlay小部件吗?我本来期望MaterialApp或Scaffold会创建一个可以在这里使用的Overlay小部件。 - masus04
5
基本上,MaterialApp在幕后创建了这个Overlay,但是每当我们使用“builder”参数时,默认情况下由MaterialApp创建的所有内容都不再被创建,必须在“builder”中手动创建,包括Overlay。 - Coala Jedi
神奇!解决所有与叠加相关的问题。 - Konstantin

5

如果您正在使用responsive_framework: ^0.1.4包,并且遇到了该问题,这里是解决方法:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter App',
      home: MyHomePage(),
      builder: (context, child) {
        return Overlay(
          initialEntries: [
            OverlayEntry(
              builder: (context) {
                return ResponsiveWrapper.builder(
                  MyHomePage(),
                  defaultScale: true,
                  breakpoints: [
                    ResponsiveBreakpoint.autoScale(1000),
                  ],
                );
              },
            ),
          ],
        );
      },
    );
  }
}

1
这个可以工作,但是如果你只是在响应式框架演示的构建器中删除箭头函数并切换为常规函数,它也会消除错误。 - Ali Türkay Avci

1

相反,每个路由中使用您的LayoutTemplate小部件:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // ... basic info title & theme

      initialRoute:"/home",
      routes: [
        '/home': (context) => LayoutTemplate(child: Text('Home')),
        // etc, for other routes
      ],
    );
  }
}

builder参数最好用于在Navigator上方或在使用WidgetsApp.router构造函数时,在Router下方但在WidgetsApp小部件创建的其他小部件下方插入可继承小部件,或者完全替换Navigator/Router

WidgetsApp.builder文档:

例如,从传递给[路由生成器方法]的BuildContext中,DirectionalityLocalizationsDefaultTextStyleMediaQuery等都可用。它们也可以以影响Navigator或Router中所有路由的方式进行覆盖。


-2
我通过使用 home 而不是 builder 参数来解决了这个问题。
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ... //basic info title & theme

      home: LayoutTemplate(child: child),
      initialRoute:"/home",

      ... //Routing stuff like generate route & navigator key 
    );
  }
}

使用builder(...)是构建页面的有效方式,如果在该builder中添加一个AppBar到Scaffold中,它不应该失败。 - Je Suis Alrick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接