6
votes

I am trying to insert a Container to the Overlay, but I had an error with this code.

class _MyHomePageState extends State<MyHomePage> {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final entry = OverlayEntry(builder: (BuildContext overlayContext) {
      return Container(
        height: 50.0,
        width: 50.0,
        color: Colors.blue,
      );
    });
    _addOverlay(entry);
  }

  void _addOverlay(OverlayEntry entry) async {
    Overlay.of(context).insert(entry);
  }

  @override
  Widget build(BuildContext context) {
   return Scaffold(
      appBar: AppBar(
        title: Text('Flutter'),
      ),
      body: Center(),
    );
  }
}

This is error

setState() or markNeedsBuild() called during build. This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase...

Thank you in advance.

2

2 Answers

10
votes

Since the last update to flutter 0.8.1 I noticed this change too. I fixed this to add the overlay after a minimal delay

Timer.run(() { Overlay.of(context).insert(calendarOverlay);});

Now this works but it feels like a hack...

So in my build i use this code when the overlay should present itself..

If anyone has a better solution, I am interested ;-)

John

UPDATE: I found this code to be working too:

final overlay = Overlay.of(context);
WidgetsBinding.instance.addPostFrameCallback((_) => overlay.insert(entry));

It saves me from including timers...

3
votes

Just share some of my findings. I am about to implement overlay in my app too. So found this SO question by searching.

Many people build overlay before the normal widget. For example, in your code, the overlay insert in didChangeDependencies is called before building the Scaffold. This is the cause of all the async problems. I found people do this (couple the overlay insert and corresponding normal widget in a stateful widget) is because they want to find the corresponding child widget's position, but the child widget is build after the overlay insert call, thus the overlay insert has to be in an async function.

But If you just call overlay insert after building the normal widget (make overlay insert call independent from building the base widget. Separate/decouple them), you won't need any async or Timer functions at all. In my current implementation, I separate them just to make the code safe (I feel it's safer). So no need for any async calls.