Abhijith
Abhijith

Reputation: 2327

Keep the bottom navigation bar in every screens flutter

I have this bottom navigation bar with center docked floating icon,the bottom bar is present and i can go through the tab elements in bottombar but i need to show the bottom bar fixed to every screen,what ever screen i open i need to show the bottombar navigation

1.How can i view the bottombar in subpages example if i goto home screen and i am going click an item in hompage and redirect next page then the bottom nav bar should show in the redirected page

Bottombar navigation

class BottomViewScreenState extends State<BottomViewScreen> {
  TabController tabController;

 static int _selectedTab = 0;
  final List<Widget> _children = [
    new HomeScreen(),
    new OfferScreen(),
    new HelpScreen(),
    new ProfileScreen(),
    new CartViewScreen(),
  ];

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      theme: ThemeData(
        primaryColor: Color(0xffFF5555),
      ),
      home: Scaffold(
        body: _children[_selectedTab], // new
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            // new CartViewScreen();
            //onTabTapped(4);
            // CartViewScreen();
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => CartViewScreen(),
              ),
            );
          },
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              Icon(Icons.add_shopping_cart),
              Text(
                "CART",
                style: TextStyle(fontSize: 8.0),
              ),
            ],
          ),
          backgroundColor: Colors.indigo[900],
          foregroundColor: Colors.white,
          elevation: 2.0,
        ),
        bottomNavigationBar: BottomAppBar(
          clipBehavior: Clip.antiAlias,
          notchMargin: 10.0,
          shape: CircularNotchedRectangle(),
          child: SizedBox(
            height: 80,
            child: 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.amberAccent,
                  textTheme: Theme.of(context)
                      .textTheme
                      .copyWith(caption: new TextStyle(color: Colors.grey))),
              child: BottomNavigationBar(
                type: BottomNavigationBarType.fixed,
                onTap: onTabTapped,
                currentIndex: _selectedTab,
                fixedColor: Colors.amberAccent,
                items: [
                  BottomNavigationBarItem(
                    icon: Icon(Icons.home),
                    title: Text(
                      'HOME',
                      style: TextStyle(fontSize: 10.0),
                    ),
                    activeIcon: Column(
                      children: <Widget>[
                        Icon(Icons.local_offer),
                      ],
                    ),
                  ),
                  BottomNavigationBarItem(
                      icon: SvgPicture.asset(
                        "assets/images/ic_bottom_offer.svg",
                        height: 25,
                        color: Colors.grey,
                      ),
                      title: Text('OFFERS', style: TextStyle(fontSize: 10.0))),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.info_outline),
                      title: Text('HELP', style: TextStyle(fontSize: 10.0))),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.people),
                      title: Text('PROFILE', style: TextStyle(fontSize: 10.0))),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  void onTabTapped(int index) {
    setState(() {
      _selectedTab = index;
    });
  }
}

Main

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "App",
      home: new SplashScreen(),
      routes: {
        "/homescreen": (_) => new BottomViewScreen(),
        "/login":(_) => new LoginScreen(),
       
      },
    );
  }
}

Upvotes: 4

Views: 23712

Answers (5)

Abhijith
Abhijith

Reputation: 2327

I have this figured it out with using this plugin Presistant_bottom_nav_bar.now i can use bottomnavbar on every screen

PersistentTabController _controller =PersistentTabController(initialIndex: 0);

//Screens for each nav items.
  List<Widget> _NavScreens() {
    return [
     HomeScreen(),
     OfferScreen(),
     HelpScreen(),
     ProfileScreen(),
     CartViewScreen(),
      
    ];
  }


  List<PersistentBottomNavBarItem> _navBarsItems() {
    return [
      PersistentBottomNavBarItem(
       icon: Icon(Icons.home),
        title: ("Home"),
        activeColorPrimary: CupertinoColors.activeBlue,
        inactiveColorPrimary: CupertinoColors.systemGrey,
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.favorite),
        title: ("OFFERS"),
        activeColorPrimary: CupertinoColors.activeGreen,
        inactiveColorPrimary: CupertinoColors.systemGrey,
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.person_pin),
        title: ("Help"),
        activeColorPrimary: CupertinoColors.systemRed,
        inactiveColorPrimary: CupertinoColors.systemGrey,
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.local_activity),
        title: ("ProfileScreen"),
        activeColorPrimary: CupertinoColors.systemIndigo,
        inactiveColorPrimary: CupertinoColors.systemGrey,
      ),
 PersistentBottomNavBarItem(
        icon: Icon(Icons.shop_cart),
        title: ("Cart"),
        activeColorPrimary: CupertinoColors.systemIndigo,
        inactiveColorPrimary: CupertinoColors.systemGrey,
      ),

    ];
  }
@override
Widget build(BuildContext context) {
    return Center(
      child: PersistentTabView(
        controller: _controller,
        screens: _NavScreens(),
        items: _navBarsItems(),
        confineInSafeArea: true,
        backgroundColor: Colors.white,
        handleAndroidBackButtonPress: true,
        resizeToAvoidBottomInset: true,
        hideNavigationBarWhenKeyboardShows: true,
        decoration: NavBarDecoration(
          borderRadius: BorderRadius.circular(10.0),
        ),
        popAllScreensOnTapOfSelectedTab: true,
        navBarStyle: NavBarStyle.style9,
      ),
    );
}

If you don't want navbar on certain screen you can use following navigator,for more info checkout persistent_bottom_nav_bar documentation

 pushNewScreen(
        context,
        screen: MainScreen(),
        withNavBar: false, // OPTIONAL VALUE. True by default.
        pageTransitionAnimation: PageTransitionAnimation.cupertino,
    );

Upvotes: 8

Bensal
Bensal

Reputation: 4130

MaterialApp(
title: 'Flutter Demo',
initialRoute:"/home",
routes: [
...
],
builder: (context, child) {
return Stack(
  children: [
    child!,
    Overlay(
      initialEntries: [
        OverlayEntry(
          builder: (context) {
            return YourCustomWidget(); *//This widget now appears on all  pages*
          },
        ),
      ],
    ),
  ],
);
},

Upvotes: 0

Tanuj
Tanuj

Reputation: 2270

There are two approaches you can handle this scenario -

The page view approch is already discussed above, I will be explaining the IndexedStack approach -

An IndexedStack is an extension of the Stack widget in Flutter, As opposed to a Stack Widget which displays all the children on top of each other based on index in the list, a Indexed widget only shows a single child in children list.

An IndexedStack has two important properties -

  • index : This determines the index of the child to be show from the children list.
  • children : A list of all available children.

The following code show the implementation to tackle above problem -

Create a stateful widget to hold the list of all possible views, current index of the view to be displayed and the bottom navigation bar.

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  
  int _currentIndex = 0;
  const List<Widget> _pages = <Widget>[
    HomeView(),
    OffersView(),
    HelpView(),
    ProfileView(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        top: false,
        child: IndexedStack(
          index: _currentIndex,
          children: _pages,
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: (int index) {
          setState(() {
            _currentIndex = index;
          });
        },
        items: [
                  BottomNavigationBarItem(
                    icon: Icon(Icons.home),
                    title: Text(
                      'HOME',
                      style: TextStyle(fontSize: 10.0),
                    ),
                    activeIcon: Column(
                      children: <Widget>[
                        Icon(Icons.local_offer),
                      ],
                    ),
                  ),
                  BottomNavigationBarItem(
                      icon: SvgPicture.asset(
                        "assets/images/ic_bottom_offer.svg",
                        height: 25,
                        color: Colors.grey,
                      ),
                      title: Text('OFFERS', style: TextStyle(fontSize: 10.0),
                    ),
                  ),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.info_outline),
                      title: Text('HELP', style: TextStyle(fontSize: 10.0),
                    ),
                  ),
                  BottomNavigationBarItem(
                      icon: Icon(Icons.people),
                      title: Text('PROFILE', style: TextStyle(fontSize: 10.0),
                    ),
                  ),
                ],
      ),
    );
  }
}

Finally run the application -

void main() {
  runApp(MaterialApp(home: HomePage(), debugShowCheckedModeBanner: false));
}

And we are done!

Upvotes: 5

Anoop
Anoop

Reputation: 66

i also recommend using IndexedStack as parent widget, as it saves widget state(if you are having static pages no need to)

  int _selectedIndex = 0;

  static List<Widget> _widgetOptions = <Widget>[
    Widget1(),
    Widget2(),
    Widget3(),
  ];

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

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

      body: IndexedStack(
        index: _selectedIndex,
        children: _widgetOptions),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Widget 1'),
          ),
          BottomNavigationBarItem(
            icon: Icon(
              Icons.note),
            title: Text('Widget 2'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.message),
            title: Text('Widget 3'),
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.black,
        unselectedItemColor: Colors.grey,
        onTap: _onItemTapped,
      ),
    );
  }

Upvotes: 1

darkness
darkness

Reputation: 183

In my project same the situation above: navigation bar handles 4 page

List<Widget> homeTap = [
  HistoryView(),
  ScanView(),
  SearchView(),
  FavoriteView()
];

And inside SearchView contains many pages.

    class SearchView extends StatefulWidget {
  @override
  _SearchViewState createState() => _SearchViewState();
}

   

     class _SearchViewState extends State<SearchView> {
          @override
          Widget build(BuildContext context) {
            final provider = Provider.of<SearchProvider>(context, listen: false);
            return PageView(
              controller: provider.pageController,
              physics: const NeverScrollableScrollPhysics(),
              children: <Widget>[
                CategoryView(),
                CategoryDetailView(),
                buildDetailPage(),
              ],
            );
          }
       
        }

If you want to navigation any page: use pageController.nextPage or jumToPage

Upvotes: 1

Related Questions