【问题标题】:Keep the bottom navigation bar in every screens flutter在每个屏幕中保持底部导航栏颤动
【发布时间】:2020-10-13 02:24:37
【问题描述】:

我有这个带有中心停靠浮动图标的底部导航栏,底部栏存在,我可以浏览底部栏中的标签元素,但我需要显示固定到每个屏幕的底部栏,无论我打开什么屏幕我都需要显示底部导航栏

1.如果我转到主屏幕并且我要单击主页中的一个项目并重定向下一页,我如何查看子页面中的底部栏,然后底部导航栏应该显示重定向的页面

底部导航

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;
    });
  }
}

主要

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(),
       
      },
    );
  }
}

【问题讨论】:

  • 您可以使用页面视图来包含您想要导航的小部件
  • 你能用一些代码解释一下吗? @黑暗

标签: flutter dart flutter-layout


【解决方案1】:

使用这个插件Presistant_bottom_nav_bar我已经解决了这个问题。现在我可以在每个屏幕上使用底部导航栏

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"),
        activeColor: CupertinoColors.activeBlue,
        inactiveColor: CupertinoColors.systemGrey,
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.favorite),
        title: ("OFFERS"),
        activeColor: CupertinoColors.activeGreen,
        inactiveColor: CupertinoColors.systemGrey,
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.person_pin),
        title: ("Help"),
        activeColor: CupertinoColors.systemRed,
        inactiveColor: CupertinoColors.systemGrey,
      ),
      PersistentBottomNavBarItem(
        icon: Icon(Icons.local_activity),
        title: ("ProfileScreen"),
        activeColor: CupertinoColors.systemIndigo,
        inactiveColor: CupertinoColors.systemGrey,
      ),
 PersistentBottomNavBarItem(
        icon: Icon(Icons.shop_cart),
        title: ("Cart"),
        activeColor: CupertinoColors.systemIndigo,
        inactiveColor: 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,
      ),
    );
}

如果您不想在某些屏幕上显示导航栏,您可以使用以下导航器,更多信息请查看persistent_bottom_nav_bar documentation

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

【讨论】:

    【解决方案2】:
    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*
              },
            ),
          ],
        ),
      ],
    );
    },
    

    【讨论】:

      【解决方案3】:

      有两种方法可以处理这种情况 -

      页面视图方法已经在上面讨论过,我将解释 IndexedStack 方法 -

      IndexedStack 是 Fl​​utter 中 Stack 小部件的扩展,与 Stack 小部件根据列表中的索引将所有子级显示在彼此之上的堆栈小部件相反,索引小部件仅显示子级中的单个子级列表。

      IndexedStack 有两个重要的属性 -

      • index :这决定了要从孩子列表中显示的孩子的索引。
      • children :所有可用子级的列表。

      以下代码显示了解决上述问题的实现 -

      创建一个有状态的小部件来保存所有可能视图的列表、要显示的视图的当前索引和底部导航栏。

      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),
                          ),
                        ),
                      ],
            ),
          );
        }
      }
      

      最后运行应用程序 -

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

      我们完成了!

      【讨论】:

      • 我实际上需要显示到孩子的子页面中,我怎样才能做到这一点..? @Tanuj Wagh
      • 如果我需要在某些情况下没有底部导航栏怎么办?
      【解决方案4】:

      我还建议使用 IndexedStack 作为父小部件,因为它可以保存小部件状态(如果您有静态页面则不需要)

        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,
            ),
          );
        }
      

      【讨论】:

      • 我实际上需要显示到孩子的子页面中,我怎样才能做到这一点..? @Anoop
      • 将你的底部导航代码分离到另一个类中,并在你所有需要的类中引用它
      【解决方案5】:

      在我的项目中与上述情况相同: 导航栏处理4页

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

      而且 SearchView 里面包含很多页面。

          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(),
                    ],
                  );
                }
             
              }
      

      如果你想导航任何页面:使用 pageController.nextPage 或 jumToPage

      【讨论】:

      • 你能在我的代码中做这样的事情吗@darkness
      猜你喜欢
      • 2018-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 2020-08-31
      • 2020-03-06
      相关资源
      最近更新 更多