33

I am a beginner with flutter and dart. I have been trying to implement a navigationBar on three different pages in my app. The toggling works well for an individual page but I have problems persisting the active and inactive tabs state on all the pages. It seems like when it navigates to another page, I lose the active state too the tabs. This is my code.

AppFooter.dart

import 'package:flutter/material.dart';

class AppFooter extends StatefulWidget {
  @override
  _AppFooterState createState() => _AppFooterState();
}

class _AppFooterState extends State<AppFooter> {
  int index = 0;
  @override
  Widget build(BuildContext context) {
    return new Theme(
      data: Theme.of(context).copyWith(
          // sets the background color of the `BottomNavigationBar`
          canvasColor: Colors.white,
          // sets the active color of the `BottomNavigationBar` if `Brightness` is light
          primaryColor: Colors.green,
          textTheme: Theme.of(context)
              .textTheme
              .copyWith(caption: new TextStyle(color: Colors.grey))),
      child: new BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          currentIndex: index,
          onTap: (int index) {
            setState(() {
              this.index = index;
            });
          switch (index){
            case 0:  Navigator.of(context).pushNamed('/dashboard');
            break;
            case 1:  Navigator.of(context).pushNamed('/medical centre');
            break;
            case 2:  Navigator.of(context).pushNamed('/history');
            break;

          }

          },
          items: [
            new BottomNavigationBarItem(
                backgroundColor: Colors.white,
                icon: index==0?new Image.asset('assets/images/dashboard_active.png'):new Image.asset('assets/images/dashboard_inactive.png'),
                title: new Text('Dashboard', style: new TextStyle(fontSize: 12.0))),
           new BottomNavigationBarItem(
               backgroundColor: Colors.white,
               icon: index==1?new Image.asset('assets/images/medical_sevice_active.png'):new Image.asset('assets/images/medical_sevice_inactive.png'),
               title: new Text('Health Services', style: new TextStyle(fontSize: 12.0))),
            new BottomNavigationBarItem(
                icon: InkWell(
                  child: Icon(
                    Icons.format_align_left,
                   // color: green,
                    size: 20.0,
                  ),
                ),
                title: new Text('History', style: new TextStyle(fontSize: 12.0))),
          ]),
    );
  }
}
Dharmik Thakkar
  • 1,650
  • 1
  • 9
  • 18
bennycodest
  • 379
  • 1
  • 5
  • 14
  • https://stackoverflow.com/questions/49628510/flutter-keep-bottomnavigationbar-when-push-to-new-screen-with-navigator/76584738#76584738 – Maciej Szakacz Jun 29 '23 at 21:41

16 Answers16

26

If I understand your question correctly, you need the bottom navigation bar persisted on all three pages. There is a well-written article on how to achieve it. You can find the details here.

https://medium.com/coding-with-flutter/flutter-case-study-multiple-navigators-with-bottomnavigationbar-90eb6caa6dbf

https://github.com/bizz84/nested-navigation-demo-flutter

All credits go to the original author.

Abin
  • 1,699
  • 1
  • 14
  • 17
  • 1
    From the above example, There Red, Green and Blue navigation. What if Red Screen contains few navigation? – Mahesh Mar 26 '20 at 16:25
  • 1
    I tried the above approach and found out the big problem is that when we change 1 tab, it will trigger the build method of other tabs which is very bad for performance I think. Just add the log line in the build method of other tabs, you'll see the log line is called every time changing the tab. – Tuan van Duong Apr 29 '21 at 01:03
  • @TuanvanDuong I think the reason for building every other tab is to keep the state; obviously there are other ways to handle this but it seems that's why. – Cl0ud-l3ss Jun 06 '21 at 18:52
  • 1
    @Cl0ud-l3ss I found a very good solution from [here](https://stackoverflow.com/a/66404760/2328861). This solution even doesn't use `CupertinoTabBar`. – Tuan van Duong Jun 10 '21 at 09:58
13

Use PageView and bottomNavigationBar:

import 'package:flutter/material.dart';

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

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

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

class App extends StatefulWidget {
  App({Key key}) : super(key: key);
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  PageController _myPage;
  var selectedPage;

  @override
  void initState() {
    super.initState();
    _myPage = PageController(initialPage: 1);
    selectedPage = 1;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: PageView(
          physics: NeverScrollableScrollPhysics(),
          controller: _myPage,
          children: <Widget>[
            Center(
              child: Text("Another Page"),
            ),
            Center(
                child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text("Page 1"),
                RaisedButton(
                  onPressed: () {
                    _myPage.jumpToPage(0);
                    setState(() {
                      selectedPage = 0;
                    });
                  },
                  child: Text("Go to another page"),
                )
              ],
            )),
            Center(child: Text("Page 2")),
            Center(child: Text("Page 3")),
          ],
        ),
        bottomNavigationBar: BottomAppBar(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              IconButton(
                icon: Icon(Icons.home),
                color: selectedPage == 1 ? Colors.blue : Colors.grey,
                onPressed: () {
                  _myPage.jumpToPage(1);
                  setState(() {
                    selectedPage = 1;
                  });
                },
              ),
              IconButton(
                icon: Icon(Icons.star),
                color: selectedPage == 2 ? Colors.blue : Colors.grey,
                onPressed: () {
                  _myPage.jumpToPage(2);
                  setState(() {
                    selectedPage = 2;
                  });
                },
              ),
              IconButton(
                icon: Icon(
                  Icons.settings,
                ),
                color: selectedPage == 3 ? Colors.blue : Colors.grey,
                onPressed: () {
                  _myPage.jumpToPage(3);
                  setState(() {
                    selectedPage = 3;
                  });
                },
              ),
            ],
          ),
        ));
  }
}

In addition, if you want preserve the state between pages such that going to another page won't cause the previous page to lose its state, use AutomaticKeepAliveClientMixin

Also, to lazily load the pages, PageView.builder is another solution.

Hope it helps.

Mais Alheraki
  • 387
  • 2
  • 4
  • Please show some more details on how it will work to help those who might face this problem in future. – Nabil Farhan Sep 20 '19 at 00:27
  • Yes, you are right! sorry about that, edited my answer – Mais Alheraki Sep 20 '19 at 16:52
  • 1
    Youre loading all your pages simultaneously and unnecessarily. Not performatic. – Guilherme Ferreira Feb 20 '21 at 04:42
  • @GuilhermeFerreira take a look here: https://stackoverflow.com/questions/66404759/flutter-nested-routing-with-persistent-bottomnavigationbar-but-without-building/66404760#66404760 – filipetrm Feb 28 '21 at 00:27
  • 3
    If I get the question correctly, he was losing the state once going between pages, ideally I want the state to be preserved between pages, which is why using a PageView is a simple solution. Just with `AutomaticKeepAliveClientMixin` approaching this in some or all pages is easy. https://api.flutter.dev/flutter/widgets/AutomaticKeepAliveClientMixin-mixin.html In addition, if you want to lazily load the pages, using `PageView.builder` can achieve this as well. – Mais Alheraki Aug 24 '21 at 09:24
  • @Nick can you explain more what kind of routing you mean? – Mais Alheraki Aug 24 '21 at 09:27
11

Another great solution is the persistent_bottom_nav_bar package provided by Bilal Shahid.

It is easy to use and offers you a bunch of features:

  • Highly customizable persistent bottom navigation bar.
  • Ability to push new screens with or without bottom navigation bar.
  • 20 styles for the bottom navigation bar.
  • Includes functions for pushing screen with or without the bottom navigation bar i.e. pushNewScreen() and pushNewScreenWithRouteSettings().
  • Based on flutter's Cupertino(iOS) bottom navigation bar.
  • Can be translucent for a particular tab.
  • Custom styling for the navigation bar. Click here for more information. Handles hardware/software Android back button.

Before I found this package I followed the solution from the article @Abin mentioned in his answer. But I ran into the problem, that all screens from the navbar beeing loaded on first load of the navbar which is not that perfomant. I did not mangaed to solve this, but luckily Bilal Shahid provide a good solution with his package.

All credits to him.

Matthias
  • 3,729
  • 22
  • 37
6

Just copy & past :)

main.dart:

void main() async{
  runApp(MyGrillApp());
}

class MyGrillApp extends StatelessWidget {
  const MyGrillApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(

      routes: {
        '/mainlayout': (context) => MainLayout(),
        '/page1': (context) => Page1(),
        '/page2': (context) => Page2(),
        '/page3': (context) => Page3(),
        '/page4': (context) => Page4(),
      },
      initialRoute: '/mainlayout',
    );
  }
}

main_layout.dart:

class MainLayout extends StatefulWidget {
  @override
  _MainLayoutState createState() => _MainLayoutState();
}

class _MainLayoutState extends State<MainLayout> {
  int _currentIndex = 0;

  final _page1 = GlobalKey<NavigatorState>();
  final _page2 = GlobalKey<NavigatorState>();
  final _page3 = GlobalKey<NavigatorState>();
  final _page4 = GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButtonLocation: FloatingActionButtonLocation.miniCenterDocked,
      floatingActionButton: Padding(
        padding: const EdgeInsets.all(6.0),
        child: FloatingActionButton(
          backgroundColor: Colors.redAccent,
          child: const Icon(Icons.add, color: Colors.white),
          onPressed: () {
            // ToDo...
          },
        ),
      ),
      body: IndexedStack(
        index: _currentIndex,
        children: <Widget>[
          Navigator(
            key: _page1,
            onGenerateRoute: (route) => MaterialPageRoute(
              settings: route,
              builder: (context) => Page1(),
            ),
          ),
          Navigator(
            key: _page2,
            onGenerateRoute: (route) => MaterialPageRoute(
              settings: route,
              builder: (context) => Page2(),
            ),
          ),
          Navigator(
            key: _page3,
            onGenerateRoute: (route) => MaterialPageRoute(
              settings: route,
              builder: (context) => Page3(),
            ),
          ),
          Navigator(
            key: _page4,
            onGenerateRoute: (route) => MaterialPageRoute(
              settings: route,
              builder: (context) => Page4(),
            ),
          ),
        ],
      ),
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(),
        clipBehavior: Clip.antiAlias,
        child: BottomNavigationBar(
          backgroundColor: Colors.white,
          currentIndex: _currentIndex,
          onTap: (index) {
            setState(() {
              _currentIndex = index;
            });
          },
          type: BottomNavigationBarType.fixed,
          selectedItemColor: Colors.redAccent,
          unselectedItemColor: Colors.grey,
          showSelectedLabels: false,
          showUnselectedLabels: false,
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
            BottomNavigationBarItem(icon: Icon(Icons.date_range), label: 'Statistics'),
            BottomNavigationBarItem(icon: Icon(Icons.wallet_giftcard), label: 'Wallet'),
            BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
          ],
        ),
      ),
    );
  }
}

Details screen:

class ItemDetailsPage extends StatefulWidget {
  const ItemDetailsPage({Key? key}) : super(key: key);

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

class _ItemDetailsPageState extends State<ItemDetailsPage> with AutomaticKeepAliveClientMixin{
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
        appBar: AppBar(
          backgroundColor: themeColorPrimary,
          title: Text('Item details',),
        ),
        body : Container(child: Text('Hello from details'),));
  }

  @override
  bool get wantKeepAlive => true;
}

A note about routing in my solution:

If you encounter trouble when you routing by:

Navigator.pushNamed(context, '/page3'); 

or by:

Navigator.of(context).pushNamed(Page3());

You can fix it using MaterialPageRoute:

Navigator.pushReplacement(
  context,
  MaterialPageRoute(
    builder: (context) => Page3(),
  ),
);
Husam Ebish
  • 4,893
  • 2
  • 22
  • 38
  • What if, I am in the home page and then I use the bottom navigator to navigate to page B. From Page B I have an action button on my AppBar that uses Navigator.of(context).pushNamed(Page_C) to go to Page C. Then the last navigation will not work. – A.Ktns Nov 30 '21 at 20:28
  • @A.Ktns thank you for the note. You are right, Navigator.of(context).pushNamed(Page_C); and Navigator.pushNamed(context, '/path'); will not work any morem, instead I use pushReplacement: Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => const NoGrillsPage(), ), ); I will update my answear – Husam Ebish Dec 01 '21 at 18:04
  • your code is working fine. but when I navigate to other page from home page (for example) and tap on home from bottom nav bar, app do not come back to the home page. – Taufiq Ahommed Neloy Feb 16 '22 at 07:50
2

You can use IndexedStack to persist State when you touch/change the page

Scaffold(
  body: SafeArea(
    top: false,
    child: IndexedStack(
      //Permet de garder le state des vues même quand on change de vue
      index: _currentIndex,
      children: _children,
    ),
  ),
  bottomNavigationBar: BottomNavigationBar( items: [ ] ),
);
Sravan
  • 1,891
  • 4
  • 23
  • 28
2

I highly recommend using stack. This gives you pretty much total control over how and when you would like to show bottom app bar.

Make list of all pages you want to show using your botttomAppBar. Let's say has three icons.

final List<Widget> pages=[FirstScreen(),SecondScreen(),ThirdScreen()];

In the Build Method

Scaffold(
 child: Stack(
  children: <Widget>[
    Navigator(
              key: _navigatorKey,
              onGenerateRoute: (RouteSettings settings) { 
                return MaterialPageRoute(
                  builder: (BuildContext context) => pages[cur_ind],
           );
        },
      ),
   ],
   bottomNavigationBar: BottomNavigationBar(

        onTap: (int index){
           
            setState(() {
             
              cur_ind=index;
              
            });

        },
        currentIndex: cur_ind,
        fixedColor: Colors.green, //let's say

        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.mail),
            title: Text('Messages'),
          ),
          BottomNavigationBarItem(
              icon: Icon(Icons.person), title: Text('Profile'))
        ],
      ),
  ),
),

where cur_ind is the variable used to control which page to show. And since the body is stacked, the Bottom Navigation Bar will be persistent always.

Saurabh Kumar
  • 2,088
  • 14
  • 17
2

For anyone looking for this in the future auto_route handle this pretty much well with very little boilerplate using AutoTabsScaffold.

  Widget build(context) {
    return AutoTabsScaffold(
        routes: const [
          BooksRouter(),
          AccountRouter(),
        ],
        bottomNavigationBuilder: (_, tabsRouter) {
          return BottomNavigationBar(
            currentIndex: tabsRouter.activeIndex,
            onTap: tabsRouter.setActiveIndex,
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.book),
                label: 'Books',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.account_box),
                label: 'Account',
              ),
            ],
          );
        },
      );
    }

henriquedn
  • 53
  • 7
  • 2
    [go_router](https://pub.dev/packages/go_router) similar to auto_route is now officially published by [flutter.dev](https://pub.dev/publishers/flutter.dev/packages) – henriquedn Oct 21 '22 at 16:07
1

I created a small, super easy to use package that let you do that effect CustomNavigator. And wrote a tutorial about it on Medium you can find it here.

So it goes like this

// Here's the custom scaffold widget
// It takes a normal scaffold with mandatory bottom navigation bar
// and children who are your pages
CustomScaffold(
  scaffold: Scaffold(
    bottomNavigationBar: BottomNavigationBar(
      items: _items,
    ),
  ),

  // Children are the pages that will be shown by every click
  // They should placed in order such as
  // `page 0` will be presented when `item 0` in the [BottomNavigationBar] clicked.
  children: <Widget>[
    Page('0'),
    Page('1'),
    Page('2'),
  ],

  // Called when one of the [items] is tapped.
  onItemTap: (index) {},
);

The cool thing about this library that it works efficiently. It creates a nested navigator (which is very unpleasant to do) and uses it for navigation in your widget tree. And of course you can always use the default navigator from MaterialApp

1

If you are looking for a solution that performs well (that doesn't build the tabs/pages unnecessarily) even using IndexedStack take a look at my answer here

filipetrm
  • 523
  • 6
  • 13
  • this works perfectly for my use case, you can look at the youtube video that explain how to use it [Here](https://www.youtube.com/watch?v=_O0PPD1Xfbk&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=47) – ABDERRAHMANE OUALI Apr 04 '21 at 18:31
0

I am working on a beta version of an express_app plugin, which achieve the required result.

Two days ago, I implemented an addition where you can set an ExpressHome and it can be any part of your tree, in addition to setting your routes of course. When changing the routes, everything under ExpressHome will change only and the rest will stay the same (i.e. you can have a permanent bar easily.

I will publish a more-recent version this evening, and if you would like a specific demo about your use case, let me know.

Smily
  • 2,732
  • 1
  • 15
  • 20
0

i had this issue too...after days of research i came across this package persistent_bottom_nav_bar: ^4.0.0

it quite easy to implement.

Anakor Divine
  • 23
  • 1
  • 4
  • but with the persistent bottom_nav_bar, the app bar appears just below the status bar. i mean like, right down to the status bar which is not neat. – Trouble Maker Apr 23 '23 at 07:44
0

You can use a scaffold widget to contain the whole screen then put IndexedStack widget as a Body option then use at the bottom navigation option in the scaffold widget you favorite implementation of the bottom navigation bar

Scaffold(
      // here is the IndexedStack as body
      body: IndexedStack(
          index: this._bottomNavIndex,
          children: [MangaGridView(), FavoriteManga()]),
      backgroundColor: Colors.black,
      bottomNavigationBar: AnimatedBottomNavigationBar(
        icons: [
          Icons.home_outlined,
          Icons.favorite_border,
          Icons.settings,
        ],
        inactiveColor: Colors.black,
        activeIndex: this._bottomNavIndex,
        gapLocation: GapLocation.none,
        activeColor: Theme.of(context).primaryColor,
        notchSmoothness: NotchSmoothness.verySmoothEdge,
        leftCornerRadius: 32,
        rightCornerRadius: 32,
        onTap: (index) => setState(() => this._bottomNavIndex = index),
        height: 70,
        splashColor: Theme.of(context).primaryColor,
        splashRadius: 40.0,
        splashSpeedInMilliseconds: 400,
        iconSize: 34,
      ),
    );
0

If you want static bottom nav bar for every single page and not wanting persistent state you can try this code below. This code is bottom nav bar(your main page is actually this.Other pages will go from this page)

Map<int, GlobalKey<NavigatorState>> navigatorKeys = {
    0: GlobalKey<NavigatorState>(),
    1: GlobalKey<NavigatorState>(),
    2: GlobalKey<NavigatorState>(),
    3: GlobalKey<NavigatorState>(),
    4: GlobalKey<NavigatorState>(),
  };

  late final List<Widget> _widgetOptions = <Widget>[
    HomeView(companyId: 0, isDialogShow: isShow, bannerListModel: bannerList, notificationModel: notificationList),
    CategoryTabView(),
    const FavoritiesView(),
    BasketView(),
    ProfileView()
  ];

  @override
  Widget build(BuildContext context) {
    final basketProvider = Provider.of<BasketProvider>(context);
    final progressProvider = Provider.of<ProgressProvider>(context);
    final favoriteProvider = Provider.of<FavoriteProvider>(context);
    final bottomProvider = Provider.of<BottomNavBarProvider>(context);

    return Scaffold(
      bottomNavigationBar: BottomNavigationBar(
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
              icon: Image.asset(
                ImageConstants.instance.homeIcon,
                color: context.colorScheme.error,
                scale: 3,
              ),
              label: ""),
          BottomNavigationBarItem(
              icon: Image.asset(
                ImageConstants.instance.categoryIcon,
                scale: 3,
              ),
              label: ""),
          BottomNavigationBarItem(
              icon: favoriteIcon(favoriteProvider), activeIcon: favoriteIcon(favoriteProvider), label: ""),
          BottomNavigationBarItem(
              icon: badgeBasket(basketProvider, false), activeIcon: badgeBasket(basketProvider, true), label: ""),
          BottomNavigationBarItem(
              icon: Image.asset(
                ImageConstants.instance.profileIcon,
                scale: 3,
              ),
              activeIcon: Image.asset(
                ImageConstants.instance.profileRedIcon,
                scale: 3,
              ),
              label: ""),
        ],
        currentIndex: bottomProvider.selectedIndex,
        onTap: bottomProvider.onItemTapped,
      ),
      body: buildNavigator(bottomProvider),
    );
  }

  buildNavigator(BottomNavBarProvider bottomProvider) {
    return Navigator(
      key: navigatorKeys[bottomProvider.selectedIndex],
      onGenerateRoute: (RouteSettings settings) {
        return MaterialPageRoute(builder: (_) => _widgetOptions.elementAt(bottomProvider.selectedIndex));
      },
    );
  }
}

And this page is provider.

class BottomNavBarProvider with ChangeNotifier {
  int _selectedIndex = 0;

  int get selectedIndex => _selectedIndex;

  set selectedIndex(int index) {
    _selectedIndex = index;
    notifyListeners();
  }

  void onItemTapped(int index) {
    selectedIndex = index;
    notifyListeners();
  }
}

We're using globalkeys for the routing and the solution is globalkeys.When you run the codes you'll see bottom nav bar static on every page and when you tap bottom nav bar item icons every page will recompile(if you need to get some api response every time).Hope it help you.

0

Here is a complete example for those who wants to achieve the same.

import 'package:flutter/material.dart';
import 'package:get/get.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'My App',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('My App'),
        actions: [
          IconButton(
            icon: const Icon(Icons.favorite),
            onPressed: () {
              Get.offAll(() => WishlistPage(),
                  transition: Transition.noTransition);
            },
          ),
        ],
      ),
      body: const Center(
        child: Text('Home Page'),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 0,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.shopping_cart),
            label: 'Products',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
        onTap: (index) {
          if (index == 0) {
            Get.offAll(() => HomePage(), transition: Transition.noTransition);
          } else if (index == 1) {
            Get.offAll(() => ProductsPage(),
                transition: Transition.noTransition);
          } else if (index == 2) {
            Get.offAll(() => ProfilePage(),
                transition: Transition.noTransition);
          }
        },
      ),
    );
  }
}

class ProductsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Paypay'),
        actions: [
          IconButton(
            icon: const Icon(Icons.favorite),
            onPressed: () {
              Get.offAll(() => WishlistPage(),
                  transition: Transition.noTransition);
            },
          ),
        ],
      ),
      body: const Center(
        child: Text('Products Page'),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 1,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.shopping_cart),
            label: 'Products',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
        onTap: (index) {
          if (index == 0) {
            Get.offAll(() => HomePage(), transition: Transition.noTransition);
          } else if (index == 1) {
            Get.offAll(() => ProductsPage(),
                transition: Transition.noTransition);
          } else if (index == 2) {
            Get.offAll(() => ProfilePage(),
                transition: Transition.noTransition);
          }
        },
      ),
    );
  }
}

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Paypay'),
        actions: [
          IconButton(
            icon: const Icon(Icons.favorite),
            onPressed: () {
              Get.offAll(() => WishlistPage(),
                  transition: Transition.noTransition);
            },
          ),
        ],
      ),
      body: const Center(
        child: Text('Profile Page'),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 2,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.shopping_cart),
            label: 'Products',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
        onTap: (index) {
          if (index == 0) {
            Get.offAll(() => HomePage(), transition: Transition.noTransition);
          } else if (index == 1) {
            Get.offAll(() => ProductsPage(),
                transition: Transition.noTransition);
          } else if (index == 2) {
            Get.offAll(() => ProfilePage(),
                transition: Transition.noTransition);
          }
        },
      ),
    );
  }
}

class WishlistPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Paypay'),
        actions: [
          IconButton(
            icon: const Icon(Icons.favorite),
            onPressed: () {
              Get.offAll(() => WishlistPage(),
                  transition: Transition.noTransition);
            },
          ),
        ],
      ),
      body: const Center(
        child: Text('Wishlist Page'),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 0,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.shopping_cart),
            label: 'Products',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
        onTap: (index) {
          if (index == 0) {
            Get.offAll(() => HomePage(), transition: Transition.noTransition);
          } else if (index == 1) {
            Get.offAll(() => ProductsPage(),
                transition: Transition.noTransition);
          } else if (index == 2) {
            Get.offAll(() => ProfilePage(),
                transition: Transition.noTransition);
          }
        },
      ),
    );
  }
}

The output is something like this

enter image description here

-2

Navigator.of(context).pushNamed(); is for Navigation with page transition. So, in this situation, the method is not match.

You can use BottomNavigationBar with Scaffold.

example code:


class AppFooter extends StatefulWidget {
  @override
  _AppFooterState createState() => _AppFooterState();
}

class _AppFooterState extends State<AppFooter> {
  int _currentIndex = 0;

  List<Widget> _pages = [
    Text("page1"),
    Text("page2"),
    Text("page3"),
  ];


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: _currentIndex,
        onTap: (int index) {
          setState(() {
            _currentIndex = index;
          });
        },
        items: [
          new BottomNavigationBarItem(
              backgroundColor: Colors.white,
              icon: _currentIndex == 0
                  ? new Image.asset('assets/images/dashboard_active.png')
                  : new Image.asset('assets/images/dashboard_inactive.png'),
              title:
                  new Text('Dashboard', style: new TextStyle(fontSize: 12.0))),
          new BottomNavigationBarItem(
              backgroundColor: Colors.white,
              icon: _currentIndex == 1
                  ? new Image.asset('assets/images/medical_sevice_active.png')
                  : new Image.asset(
                      'assets/images/medical_sevice_inactive.png'),
              title: new Text('Health Services',
                  style: new TextStyle(fontSize: 12.0))),
          new BottomNavigationBarItem(
              icon: InkWell(
                child: Icon(
                  Icons.format_align_left,
                  // color: green,
                  size: 20.0,
                ),
              ),
              title: new Text('History', style: new TextStyle(fontSize: 12.0))),
        ],
      ),
    );
  }
}

HeavenOSK
  • 786
  • 7
  • 13
-6

Just make your index variable static like:

static int index = 0;
Paul Roub
  • 36,322
  • 27
  • 84
  • 93