Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pushing a new screen onto the stack from within the Build() method

Tags:

flutter

An app has a BottomNavigationBarItem, which, as usual, enables switching between screens.

I wish to change the functionality of one screen, so that when the orientation is switched to landscape, a different screen is pushed onto the stack. The intention is that this new screen will overlay everything and have no navigation bar.

I tried the following:

  @override
  Widget build(BuildContext context) {
    return OrientationBuilder(
        builder: (BuildContext context, Orientation orientation) {
      if (orientation == Orientation.portrait) {
         return Column(
            // regular content
         }
      } else {
        Navigator.of(context).push(MaterialPageRoute(
            builder: (context) => MyLandscapeViewWidget(module: widget.module)));
      }
  }

This will not work, because the else clause - triggered when in landscape mode - needs to return a widget.

What is the best solution?

Thanks

like image 230
user1052610 Avatar asked Jan 26 '26 21:01

user1052610


1 Answers

The issue with using Navigator.push is that it builds a new widget screen and disposes the previous one. What you are looking for is an OverlayEntry widget. OverlayEntry builds independently within its own widget tree and manages its own build lifecycle.

Here is an example demonstrating how to use OverlayEntry.

class MyOverlayScreen {
  static OverlayEntry? _overlayEntry;

  static void closeOverlayIfVisible() {
    if (_overlayEntry == null) {
      return;
    }
    _overlayEntry?.remove();
    _overlayEntry = null; 
  }

  static void show(BuildContext context) {
    if (_overlayEntry != null) return;
    _overlayEntry = OverlayEntry(
      builder: (context) {
        return const Material(
            child:Center(
                  child: Text("Overlay Screen"),
                ));
      },
    );
    Overlay.of(context).insert(_overlayEntry!);
  }
}

You can now modify your code to show/hide the overlay widget.

    OrientationBuilder(
      builder: (BuildContext context, Orientation orientation) {
          WidgetsBinding.instance.addPostFrameCallback((_) {
            if (orientation == Orientation.landscape) {
              MyOverlayScreen.show(context);
            } else {
              MyOverlayScreen.closeOverlayIfVisible();
            }
          });
...

I added PostFrameCallback to make sure the built first to eliminate the setState() or markNeedsBuild() error.

As a bonus, here is another usage example of OverlayEntry. It is used to maintain an active dialog screen even when navigating between screens https://dartpad.dev/?id=cbf43c2a652accbff41732d4489c7eb6

like image 155
Texv Avatar answered Jan 28 '26 21:01

Texv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!