Darshan
Darshan

Reputation: 11669

Exception while implementing navigator. Navigator operation requested with a context that does not include a Navigator

I started to play with flutter and trying to open a new screen after tapping on a button from main screen. I looked at similar questions asked before here and tried to follow the solutions provided, but am not quite sure how and where to implement the solution.

This is the exception I am getting :

Navigator operation requested with a context that does not include a Navigator.

I think I know the root cause of this issue, ie, the context I am trying to refer doesn't have Navigator widget in it, but not sure how to resolve it. Below is my complete code :

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    Widget phoneSection = Container(
      padding: const EdgeInsets.all(16.0),
      child: Row(
        children: <Widget>[Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[Container(
              padding: const EdgeInsets.only(bottom: 8.0),
              child: Text(
                'Welcome To City',
                textAlign: TextAlign.center,
                style: TextStyle(
                  fontWeight: FontWeight.bold,

                ),
              ),
            )
            ],
          ),
        ),
        ],
      ),
    );

    Widget buttonSection = RaisedButton(
      child: const Text('Lets Take a Tour'),
      color: Theme.of(context).primaryColor,
      elevation: 4.0,
      splashColor: Colors.blueGrey,
      onPressed: () {
        Navigator.of(context).pushNamed('/screen2');
      },
    );

    return MaterialApp(
      title: 'ATG',

      home: Scaffold(
        appBar: AppBar(
          title: Text('Tour Guide'),
        ),
        body: ListView(
          children: <Widget>[Image.asset(
            'images/bkm.png',
            width: 600.0,
            height: 240.0,
            fit: BoxFit.cover,
          ),

          phoneSection,
          buttonSection,
          ],
        ),
      ),
      routes: <String, WidgetBuilder> {
        '/screen2' : (BuildContext context) => new Screen2(),
      },
    );

  }

  void button1(BuildContext context) {
    Navigator.of(context).pushNamed('/screen2');
  }
}

class Screen2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      home: new Scaffold(
      appBar: new AppBar(
        title: new Text("Screen 2"),

      ),
    ),
    );
  }
}

I am looking for inputs as to where exactly I need to implement the Navigator widget reference with code snippet. Appreciate your help in this.

Upvotes: 0

Views: 95

Answers (1)

rmtmckenzie
rmtmckenzie

Reputation: 40433

There's a few things you're doing wrong here. The first is that you have multiple MaterialApp instances. You should only ever have one of those.

The next issue is that in your button1 method, you're using the widget's context to find a Navigator. But since the navigator is being built within that widget, it won't find it. This is essentially the context that you're using:

MyApp    <---- Context
  MaterialApp
    (Navigator)
      Scaffold 
        ...

And when you do Navigator.of(context) it starts at the current context and goes up the tree.

I'd advise splitting your app up so that you have a MyApp widget (or whatever you want to call it) ad then widgets for each screen. It's possible to do this without that by using a Builder widget, but it's a better practice to split up the build functions anyways.

This will do what you're wanting:

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 MaterialApp(
      title: 'ATG',
      home: HomeScreen(),
      routes: <String, WidgetBuilder>{
        '/screen2': (BuildContext context) => new Screen2(),
      },
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    Widget phoneSection = Container(
      padding: const EdgeInsets.all(16.0),
      child: Row(
        children: <Widget>[
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Container(
                  padding: const EdgeInsets.only(bottom: 8.0),
                  child: Text(
                    'Welcome To City',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                )
              ],
            ),
          ),
        ],
      ),
    );

    Widget buttonSection = RaisedButton(
      child: const Text('Lets Take a Tour'),
      color: Theme.of(context).primaryColor,
      elevation: 4.0,
      splashColor: Colors.blueGrey,
      onPressed: () {
        Navigator.of(context).pushNamed('/screen2');
      },
    );

    return Scaffold(
      appBar: AppBar(
        title: Text('Tour Guide'),
      ),
      body: ListView(
        children: <Widget>[
          Image.asset(
            'images/bkm.png',
            width: 600.0,
            height: 240.0,
            fit: BoxFit.cover,
          ),
          phoneSection,
          buttonSection,
        ],
      ),
    );
  }

  void button1(BuildContext context) {
    Navigator.of(context).pushNamed('/screen2');
  }
}

class Screen2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Screen 2"),
      ),
    );
  }
}

Upvotes: 2

Related Questions