MaterialPageRoute goes to a new page without the appbar using it with bottomNavigationBar

3.7k views Asked by At

I have an app with three routes and uses the bottomNavigationBar to navigate between them. In one of the routes I have a button in the page that will also navigate to one of the pages.

Heres my main page

import 'package:flutter/material.dart';

import 'page_two.dart';
import 'page_three.dart';

void main() {
  return runApp(MyApp());
}

/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _selectedIndex = 0;

  List<Widget> _widgetOptions = <Widget>[
    Text('Main'),
    PageTwo(),
    PageThree(),
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;

    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BottomNavigationBar Sample'),
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home, color: Colors.black),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business, color: Colors.black),
            title: Text('Business'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business, color: Colors.black),
            title: Text('Business'),
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

Page Two

import 'package:flutter/material.dart';

import 'main.dart';

class PageTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
        child: Text('Go page 1'),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => MyApp()),
          );
        },
      ),
    );
  }
}

and Page Three with a button that navigates to page two

import 'package:flutter/material.dart';

import 'page_two.dart';

class PageThree extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
        child: Text('Go page 1'),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => PageTwo()),
          );
        },
      ),
    );
  }
}

When I press the button on Page Three, it will go to Page Two without the AppBar and the BottomNavigationBar

2

There are 2 answers

1
chunhunghan On BEST ANSWER

Use GlobalKey and In PageTwo Widget call MyStatefulWidgetState's _onItemTapped function
You can see working demo and full code below
code snippet

final scakey = new GlobalKey<_MyStatefulWidgetState>();
...
child: Text('Go page 2'),
    onPressed: () {
      scakey.currentState._onItemTapped(1);  

enter image description here

full code

import 'package:flutter/material.dart';

void main() {
  return runApp(MyApp());
}

final scakey = new GlobalKey<_MyStatefulWidgetState>();

/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyStatefulWidget(key: scakey),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  int _selectedIndex = 0;

  final myKey = new GlobalKey<_MyStatefulWidgetState>();

  List<Widget> _widgetOptions = <Widget>[
    Text('Main'),
    PageTwo(),
    PageThree(),
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: myKey,
      appBar: AppBar(
        title: const Text('BottomNavigationBar Sample'),
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home, color: Colors.black),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business, color: Colors.black),
            title: Text('Business'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business, color: Colors.black),
            title: Text('Business'),
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

class PageTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
        child: Text('Go page 1'),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => MyApp()),
          );
        },
      ),
    );
  }
}

class PageThree extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
        child: Text('Go page 2'),
        onPressed: () {
          scakey.currentState._onItemTapped(1);
          /*Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => PageTwo()),
          );*/
        },
      ),
    );
  }
}
0
Can On

When using navigation bar to navigate between pages, you are tapping on BottomNavigationBarItem to change the index by calling setState() and as the result, build method is triggered with a new _selectedIndex and that index is used to render your appropriate widget.

_widgetOptions.elementAt(_selectedIndex)

Navigator.push on the other hand is just pushing a new route on top of the navigation stack. You are not getting an AppBar or BottomNavigationBar since you don't have them on PageTwo. What I would recommend you is to create a callback function in PageTwo and call that function on button tap. You can now use that callback in MyStatefulWidget to change the index with setState. Here is an example

Declare a final like below in your pages.

final void Function(int index) pageChanged;

In the onTap event of your button, call this function.

widget.pageChanged(1); // PageTwo

In MyStatefulWidget, when you are creating pages, pass the function.

PageTwo(pageChanged:(index){
  setState(){_selectedIndex = index;}
});