Flutter navigation, reopen page instead of pushing it again
Asked Answered
T

4

15

I'm new to flutter and I'm working on an App that have multiple screens.

I would like to know to stop flutter from creating multiple screens of the same route, for example I have Page 1 and Page 2, if I click on the button to navigate to Page 2 and clicked again on the same button the application will push a new screen of Page 2 and i will have it twice and if I click on the return button it will send me back to the first created Page 2

is there a way to create every page only once and then reopen it if it's already pushed to the stack ?

I'm using Navigator.push for all my navigation

Trotskyism answered 23/12, 2019 at 14:56 Comment(3)
On the button on Page 2 do you want to go back to Page 1? If so you should just use Navigator.of(context).pop(); and it will close Page 2 and go back to Page 1 without creating new views.Snowdrift
the button should not be visible when on page2. think of navigation as a stack. if you push page2 again there will be two instances of page2 widget on the stack.Melburn
have you resolved this issue ????Candlewick
S
7

These answers are not correct. PushReplacement will still create a new instance of the widget. That's very simple to identify if you have a scrollable list in RouteA and scroll it before navigating to a RouteB. When you pushReplacement(RouteA) , you'll see the scrolling position have changed to its initial state. That is because a new widget was instantiated, and that is not the behaviour you want.

You should use popUntil, as previously answered by JoaoSoares

Spieler answered 1/3, 2021 at 17:46 Comment(1)
In case of a drawer, for example, you don't necessarily want to pop all pages until you return to the existing one. By doing so, you'd destroy all pages of your navigation stack for the sake of returning to only one. All sacrificing for one... ^^ I'd wish there would be a method to show a page if it exists...Gabelle
F
5

Using a simple logic here

  1. If the new page is the same as the current page then use Navigator.push(context,route).

  2. If the new page is the different then use Navigator.pushReplacement(context,route).


In case if you are using named routes then for

  1. same page as current, use Navigator.pushNamed(context,name).
  2. different page, use Navigator.pushReplacementNamed(context,name).

Complete code sample

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SO(),
    );
  }
}

class SO extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageOne(),
    );
  }
}

class PageOne extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Page 1'),
      ),
      backgroundColor: Colors.amber,
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            RaisedButton(
              onPressed: () {
                print('creating replacement page 1');
                Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) {
                  return PageOne();
                }));
              },
              child: Text('Go to page 1'),
            ),
            RaisedButton(
              onPressed: () {
                print('creating new page 2');
                Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
                  return PageTwo();
                }));
              },
              child: Text('Go to page 2'),
            ),
          ],
        ),
      ),
    );
  }
}

class PageTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Page 2'),
      ),
      backgroundColor: Colors.brown,
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            RaisedButton(
              onPressed: () {
                print('creating new page 1');
                Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => PageOne()));
              },
              child: Text('Go to page 1'),
            ),
            RaisedButton(
              onPressed: () {
                print('creating replacement page 2');
                Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) => PageTwo()));
              },
              child: Text('Go to page 2'),
            ),
          ],
        ),
      ),
    );
  }
}
Feigned answered 23/12, 2019 at 15:44 Comment(1)
if you are using replacement, it will remove back navigation address.Married
K
4

You should use Navigator.pushReplacement(). Here are the docs: https://api.flutter.dev/flutter/widgets/NavigatorState/pushReplacement.html

In summary, when you call pushReplacement, it pushes a new page but also disposes of the previous one. Now, when you press the back button, it should bring you back to page 1.

Kamala answered 23/12, 2019 at 14:58 Comment(0)
E
0

You can use the following code to achieve your goal. i.e. you don't open page2 again and use the one already opened.

bool isNewRouteSameAsCurrent = false;

Navigator.popUntil(context, (route) {
  if (route.settings.name == "page2") {
    isNewRouteSameAsCurrent = true;
  }
  return true;
});

if (!isNewRouteSameAsCurrent) {
  Navigator.pushNamed(context, "page2");
}

When page2 is open, other actions providing to open page2 do not open page2 again over the existing page2.

Edraedrea answered 3/1 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.