0

Can some one help me with Flutter.

I'm trying to (Navigate to a new screen and back.)

Follow the guide here:

https://flutter.dev/docs/cookbook/navigation/navigation-basics

But i got this error here:

Another exception was thrown: Navigator operation requested with a context that does not include a Navigator.

Here is my Simple Flutter code:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget{
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp>{

  @override
  Widget build(BuildContext context){
    return new MaterialApp(
      title: 'Welcome',
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to view by view'),
        ),
        body: Center(
          child: Wrap(
            children: <Widget>[
              RaisedButton(
                child: Text('View 2'),
                onPressed: (){
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => SecondRoute()),
                  );
                },
              )
            ],
          ),
        ),
      )
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

Thanks!

fredy
  • 1
  • 2
  • 4

3 Answers3

1

Weird that the docs would recommend a broken approach! Just extract the body of the MaterialApp into its own Widget and it will work. Here's the code:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget{
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp>{

  @override
  Widget build(BuildContext context){
    return new MaterialApp(
        title: 'Welcome',
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(
            title: Text('Welcome to view by view'),
          ),
          body: FirstRoute(),
        )
    );
  }
}

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Wrap(
        children: <Widget>[
          RaisedButton(
            child: Text('View 2'),
            onPressed: (){
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => SecondRoute()),
              );
            },
          )
        ],
      ),
    );
  }
}


class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}
Eric Duffett
  • 1,654
  • 17
  • 25
  • Apparently this issue has been reported: https://github.com/flutter/flutter/issues/15919 – Eric Duffett Jul 24 '19 at 19:21
  • Your code works, but i need to have (extends State) so i can update my button live to variable Text(), thats why i have (class _MyAppState extends State{) – fredy Jul 25 '19 at 09:27
  • I need this here setState(() {}); in my RaisedButton – fredy Jul 25 '19 at 09:44
0

Wrap the widget which needs to access to Navigator into a Builder or extract that sub-tree into a class. And use the new BuildContext to access Navigator.

f-person
  • 331
  • 5
  • 16
0

Yes, in the flutter example MaterialApp is

 runApp(MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));

In the Example FirstRoute it's separated from MaterialApp. This is done because if we put the content of FirstRoute directly inside MaterialApp , then it will not have the context of MaterialApp, and it cannot acess the Navigator .

You have 2 options.

Place the Scaffold in it's own stateless Widget .

Or wrap the scaffold in a builder widget to have the MaterialApp context available

class _MyAppState extends State<MyApp>{

  @override
  Widget build(BuildContext context){
    return new MaterialApp(
      title: 'Welcome',
      debugShowCheckedModeBanner: false,
      home: Builder(builder: (BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Welcome to view by view'),
        ),
        body: Center(
          child: Wrap(
            children: <Widget>[
              RaisedButton(
                child: Text('View 2'),
                onPressed: (){
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => SecondRoute()),
                  );
                },
              )
            ],
          ),
        ),
      )})
    );
  }
}

More info in this answer

RegularGuy
  • 3,516
  • 1
  • 12
  • 29