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.
OverlayEntry is used to insert a widget into the Overlay, then Positioned or AnimatedPositioned is used to determine where it will enter within the Overlay. This is useful when you require an item to appear on top of another widget (similar to the Stack widget) without modifying your entire codebase.
In Flutter, the overlay lets you print visual elements on top of other widgets by inserting them into the overlay's stack. You insert a widget into the overlay using an OverlayEntry and you use Positioned and AnimatedPositioned to choose where the entry is positioned within the overlay.
Overlays let independent child widgets float visual elements on top of other widgets by inserting them into the overlay's Stack. This article discusses the implementation of Overlays in Flutter.
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...
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With