使用底部导航栏进行导航

3

我有一个Flutter应用程序,在我的应用程序中,我需要为每个页面显示底部导航栏。

我很困惑,是应该使用底部导航栏进行导航,还是为每个页面添加底部导航栏。

如果我使用导航,我必须将Scaffold作为所有小部件的父级,那么是否有任何方法可以使用Scaffold进行导航。

这是我的代码:


class WorkerHomeScreen extends StatelessWidget {
  WorkerHomeScreen({Key? key}) : super(key: key);
  int _selectedPageIndex = 0;

  List<Map<String, dynamic>> get _pages {
    return [
      {"page": SignInScreen(), "name": "PROPERTY", "action": null},
      {
        "page": ChoseRoleScreen(),
        "name": "CHAT",
        "action": ["Search"]
      },
      {"page": LandingPage(), "name": "VIDEO", "action": null},
      {"page": EmployerSignUpScreen(), "name": "PROFILE", "action": null}
    ];
  }

  void _selectPage(int index) {
    _selectedPageIndex = index;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: false,
      ),
      body: _pages[_selectedPageIndex]["page"],
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        onTap: _selectPage,
        currentIndex: _selectedPageIndex,
        items: [
          BottomNavigationBarItem(
            icon: Icon(workerNavigationLists[0].icon),
            label: "Property",
            activeIcon: Icon(workerNavigationLists[0].icon),
          ),
          BottomNavigationBarItem(
            icon: Icon(workerNavigationLists[1].icon),
            label: "Chat",
            activeIcon: Icon(workerNavigationLists[0].icon),
          ),
          BottomNavigationBarItem(
            icon: Icon(workerNavigationLists[0].icon),
            label: "Video",
          ),
          BottomNavigationBarItem(
            icon: Icon(workerNavigationLists[0].icon),
            label: "Profile",
            activeIcon: Icon(workerNavigationLists[0].icon),
          ),
        ],
      ),
    );
  }
}

这是我的屏幕截图:

class SignInMobile extends StatelessWidget {
  SignInMobile({Key? key}) : super(key: key);
  final SignInController signInController = Get.find();
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: RaisedButton(
          onPressed: () {
             /// I want to navigate to other page but I want navigation bar in other page also
               
             },
          child: Text("TAP TO NAVIGATE"),
        ),
      ),
    );
  }
}


https://www.javatpoint.com/flutter-bottom-navigation-bar - Anmol Mishra
谢谢你的回复,Anmol。但是我想要使用底部导航栏进行导航,而你提供的参考资料只是关于如何添加底部导航栏,这是完全不同的事情。 - Dipak Ramoliya
嗨,@DipakRamoliya,我想问一下,您是否希望保持bottomnav不变,并且当您单击navbatitem时,您可以在所选项目本身中转到不同的页面。 - Sagar Acharya
是的,Sagar,我想要和你说的一样。 - Dipak Ramoliya
好的,请等一下,我会为您创建一个示例,并在其中演示其工作。 - Sagar Acharya
@DipakRamoliya,请查看我添加的以下示例。 - Sagar Acharya
5个回答

7

从讨论中,我创建了一个例子:

点击下面的链接查看演示: https://github.com/sagaracharya24/bottomApp.git

为了实现这个效果,你需要掌握以下内容:

  1. OnGenerateRoute机制。
  2. GlobalKeys和NavigatorState。
  3. 了解Offstage widget如何在幕后工作。

这个例子能带给你什么:

  1. 每个页面都会根据BottomBarItem维护页面堆栈。
  2. 如果你在嵌套页面深处点击同一项,它将删除所有页面并回到主页面。

我还添加了一个样本GIF来展示应用程序正在工作。

请告诉我是否对你有用,谢谢。


1
我已经查看了你的实现,稍作调整后,我已经让它工作了。任何愿意获得与上述相同行为的人都应该尝试这个。谢谢。 - Pixxu Waku

2
您可以使用 persistent_bottom_nav_bar 来实现您的期望。按照以下方式进行操作:
late PersistentTabController _controller;
 @override
void initState() {
    super.initState();
    _controller = PersistentTabController(initialIndex: 0);
   
  }
     List<PersistentBottomNavBarItem> _navBarsItems() {
    return [
      PersistentBottomNavBarItem(
        icon: Image.asset('assets/logowhite.png', height: 30, width: 30),
        inactiveIcon:
            Image.asset('assets/logowhite.png', height: 30, width: 30),
        title: "Vesvusa",
        textStyle: const TextStyle(color: Colors.white),
        activeColorPrimary: MyTheme.grey,
        activeColorSecondary: Colors.white,
        contentPadding: 5,
        inactiveColorPrimary: Colors.white,
        inactiveColorSecondary: Colors.white,
        routeAndNavigatorSettings: RouteAndNavigatorSettings(
          initialRoute: '/dashboard',
          routes: {
            '/newsevents': (context) => NewsListScreen(
                menuScreenContext: context,
                hideMainAppBar: hideMainAppBar,
                itemCount: null),
            '/blogdetails': (context) => BlogDetails(
                  menuScreenContext: context,
                  hideMainAppBar: hideMainAppBar,
                ),
            '/videoslist': (context) => VideosList(menuScreenContext: context),
            '/bookings': (context) => Bookings(menuScreenContext: context),
            '/lookstheme': (context) => LooksTheme(menuScreenContext: context),
            '/catalog': (context) => Catalog(menuScreenContext: context),
            '/productdetails': (context) =>
                ProductDetails(menuScreenContext: context),
          },
        ),
      ),
      PersistentBottomNavBarItem(
        icon: Image.asset(
          'assets/search.png',
          height: 25,
          width: 25,
          color: Colors.white,
        ),
        inactiveIcon: Image.asset(
          'assets/search.png',
          height: 25,
          width: 25,
          color: Colors.white,
        ),
        title: ("Search"),
        activeColorPrimary: MyTheme.grey,
        activeColorSecondary: Colors.white,
        contentPadding: 5,
        inactiveColorPrimary: Colors.white,
        inactiveColorSecondary: Colors.white,
        routeAndNavigatorSettings: const RouteAndNavigatorSettings(
          initialRoute: '/search',
          routes: {
//            '/first': (context) => MainScreen2(),
//            '/second': (context) => MainScreen3(),
          },
        ),
      ),
      PersistentBottomNavBarItem(
        icon: Image.asset(
          'assets/favourite.png',
          height: 25,
          width: 25,
          color: Colors.white,
        ),
        inactiveIcon: Image.asset(
          'assets/favourite.png',
          height: 25,
          width: 25,
          color: Colors.white,
        ),
        title: ("Favorite"),
        activeColorPrimary: MyTheme.grey,
        activeColorSecondary: Colors.white,
        contentPadding: 5,
        inactiveColorPrimary: Colors.white,
        inactiveColorSecondary: Colors.white,
        textStyle: const TextStyle(color: Colors.white),
        routeAndNavigatorSettings: const RouteAndNavigatorSettings(
          initialRoute: '/favorite',
          routes: {
//              '/first': (context) => MainScreen2(),
//              '/second': (context) => MainScreen3(),
          },
        ),
//          onPressed: (context) {
//            pushDynamicScreen(context,
//                screen: SampleModalScreen(), withNavBar: true);
//          }
      ),
      PersistentBottomNavBarItem(
        icon: Image.asset(
          'assets/cart.png',
          height: 25,
          width: 25,
          color: Colors.white,
        ),
        inactiveIcon: Image.asset(
          'assets/cart.png',
          height: 25,
          width: 25,
          color: Colors.white,
        ),
        title: ("Cart"),
        activeColorPrimary: MyTheme.grey,
        activeColorSecondary: Colors.white,
        contentPadding: 5,
        inactiveColorPrimary: Colors.white,
        inactiveColorSecondary: Colors.white,
        textStyle: const TextStyle(color: Colors.white),
        routeAndNavigatorSettings: const RouteAndNavigatorSettings(
          initialRoute: '/cart',
          routes: {
//            '/first': (context) => MainScreen2(),
//            '/second': (context) => MainScreen3(),
          },
        ),
      ),
      PersistentBottomNavBarItem(
        icon: Image.asset(
          'assets/profile.png',
          height: 25,
          width: 25,
          color: Colors.white,
        ),
        inactiveIcon: Image.asset(
          'assets/profile.png',
          height: 25,
          width: 25,
          color: Colors.white,
        ),
        title: ("Profile"),
        activeColorPrimary: MyTheme.grey,
        activeColorSecondary: Colors.white,
        contentPadding: 5,
        inactiveColorPrimary: Colors.white,
        inactiveColorSecondary: Colors.white,
        textStyle: const TextStyle(color: Colors.white),
        routeAndNavigatorSettings: RouteAndNavigatorSettings(
          initialRoute: '/profile',
          routes: {
            '/orders': (context) => MyOrders(
                  menuScreenContext: context,
                ),
            '/loginsecurity': (context) => LoginSecurity(
                  menuScreenContext: context,
                ),
            '/payment': (context) => Payment(
                  menuScreenContext: context,
                ),
            '/message': (context) => Messages(
                  menuScreenContext: context,
                ),
            '/devices': (context) => Devices(
                  menuScreenContext: context,
                ),
            '/devices': (context) => Devices(
                  menuScreenContext: context,
                ),
            '/inboxdetails': (context) => InboxDetails(
                  menuScreenContext: context,
                ),
            '/loyalty': (context) => Loyalty(menuScreenContext: context),
          },
        ),
      ),
    ];
  }

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: MyTheme.themeColor,
      appBar:  AppBar(
              elevation: 0,
              iconTheme: IconThemeData(
                color: MyTheme.grey,
              ),
              centerTitle: true,
              backgroundColor: MyTheme.themeColor,
              title: Image.asset("assets/titles.png", height: 60, width: 100),
              actions: [
                Builder(
                  builder: (context) {
                    return InkWell(
                        onTap: () {
                          Scaffold.of(context).openEndDrawer();
                        },
                        child: Padding(
                          padding: const EdgeInsets.fromLTRB(0, 0, 20, 0),
                          child: Icon(Icons.notifications_none_outlined,
                              color: MyTheme.grey),
                        ));
                  },
                )
              ],
            ),
      drawer: MyDrawer(),
      endDrawer: const NotificationDrawer(),
      body: PersistentTabView(
        context,
        controller: _controller,
        screens: _buildScreens(),
        items: _navBarsItems(),
        confineInSafeArea: true,
        backgroundColor: MyTheme.themeColor,
        handleAndroidBackButtonPress: true,
        resizeToAvoidBottomInset: true,
        stateManagement: true,

        hideNavigationBarWhenKeyboardShows: true,
        margin: const EdgeInsets.all(0.0),
        popActionScreens: PopActionScreensType.once,
        bottomScreenMargin: 0.0,
        onWillPop: (context) async {
          await showDialog(
              context: context!,
              useSafeArea: false,
              builder: (context) => CommonAlert());
          return false;
        },
        selectedTabScreenContext: (context) {
          context = context;
        },
        hideNavigationBar: _hideNavBar,

        popAllScreensOnTapOfSelectedTab: true,

        itemAnimationProperties: const ItemAnimationProperties(
          duration: Duration(milliseconds: 200),
          curve: Curves.ease,
        ),
        screenTransitionAnimation: const ScreenTransitionAnimation(
          animateTabTransition: true,
          curve: Curves.ease,
          duration: Duration(milliseconds: 200),
        ),
        navBarStyle:
            NavBarStyle.style7, // Choose the nav bar style with this property
      ),
    );
  }

你可以通过以下方式导航到其他页面
 pushNewScreen(context,
                              screen: Loyalty(
                                menuScreenContext: context,
                              ),pageTransitionAnimation:PageTransitionAnimation.scale);
                        },

谢谢Nbn,这意味着如果我在一个屏幕上,并且想要导航到第二个屏幕,那么我必须为底部导航添加路由,它会使用底部导航栏进行导航,对于大型项目来说安全吗? - Dipak Ramoliya
是的,它适用于您应用程序的所有屏幕。 - Nabin Dhakal

2

如果你只在首页(第一页)定义了BottomNavigationBar,则无需在所有页面中添加它。


但我做得很正确,但我的应用程序有40页,我无法在所有页面上显示底部栏。 - Dipak Ramoliya
正如 @vaidarbhi 所建议的那样,如果您在主页中定义并只需将该主页导入到所有其他页面中,您就可以实现这一点。 - gretal

1

如果您不想使用任何包来维护或减小应用程序的大小,请使用内置的Flutter底部导航。

import 'package:flutter/material.dart';

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

  @override
  State<Mynavigation> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<Mynavigation> {
  int _selectedIndex = 0;
  static const TextStyle optionStyle =
  TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
   List<Widget> _widgetOptions = <Widget>[
   Home(),Business(),School(), Settings()
    
  ];

  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(
        type: BottomNavigationBarType.fixed,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
            backgroundColor: Colors.red,
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            label: 'Business',
            backgroundColor: Colors.green,
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.school),
            label: 'School',
            backgroundColor: Colors.purple,
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            label: 'Settings',
            backgroundColor: Colors.pink,
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

您注意到这一行有Home(),Business(),School(),Settings(),

这些应该是您要导航到的各个页面。所以请将它们更改为指向您要使用的页面。

还有一件事,请将Mynavigation替换为WorkerHomeScreen,然后您就可以开始了。

如果您使用的是Flutter SDK>2.12.0,请在此行上使用:

static const List<Widget> _widgetOptions = <Widget>[

如果您的SDK版本低于2.12.0,则使用以下方法:

 List<Widget> _widgetOptions = <Widget>[

如果有任何问题,请联系我。

祝你好运,兄弟!


1
感谢你的回答Smith,但我想要像在YouTube中使用底部栏一样进行导航,这不是我的答案。 - Dipak Ramoliya

0

您可以使用Scaffold属性轻松添加BottomNavigationBar,并将多个页面添加到列表中。希望您已经找到了解决方案。

import 'package:flutter/material.dart';
import 'package:traveling/helpers/AppColors.dart';
import 'package:traveling/screens/Employee/home/Home.dart';
import 'package:traveling/screens/Employee/profile/Profile.dart';
import 'package:traveling/screens/Employee/setting/Setting.dart';



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

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

class _EmployeeBottomNavBarState extends State<EmployeeBottomNavBar> {
  int pageIndex = 0;
  bool visible = true;

  List<Widget> pageList = <Widget>[EmployeeHome(), Profile(leadingIcon: false,), Setting()];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: pageList[pageIndex],
        bottomNavigationBar: BottomNavigationBar(
            fixedColor: Colors.redAccent[400],
            currentIndex: pageIndex,
            onTap: (value) {
              setState(() {
                pageIndex = value;
              });
            },
            // type: BottomNavigationBarType.fixed,
            items: [
              BottomNavigationBarItem(

                  activeIcon: Container(
                    height: 40,
                    width: 80,
                    decoration: BoxDecoration(
                      shape: BoxShape.circle,
                      color: Color(0xff2161c0),
                    ),
                    child: Icon(
                      Icons.home,
                      color: AppColors.white,
                    ),
                  ),
                  icon: Icon(
                    Icons.home,
                    color: Color(0xff2161c0),
                  ),
                  label: ""),
              BottomNavigationBarItem(
                  activeIcon: Container(
                    height: 40,
                    width: 80,
                    decoration: BoxDecoration(
                      shape: BoxShape.circle,
                      color: Color(0xff2161c0),
                    ),
                    child: Icon(
                      Icons.person,
                      color: AppColors.white,
                    ),
                  ),
                  icon: Icon(
                    Icons.person,
                    color: AppColors.baseLightBlueColor,
                  ),
                  label: ""),
              BottomNavigationBarItem(
                  activeIcon: Container(
                    height: 40,
                    width: 80,
                    decoration: BoxDecoration(
                      shape: BoxShape.circle,
                      color: AppColors.baseLightBlueColor,
                    ),
                    child: Icon(
                      Icons.settings,
                      color: AppColors.white,
                    ),
                  ),
                  icon: Icon(
                    Icons.settings,
                    color: AppColors.baseLightBlueColor,
                  ),
                  label: ""),
            ]
        )
    );
  }
}

不,这不是我的答案。 - Dipak Ramoliya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接