【问题标题】:Flutter: Persist BottomNavigationBar and route user to the correct screen depending on the selected index of the BottomNavigationBarFlutter:坚持BottomNavigationBar并根据BottomNavigationBar的选定索引将用户路由到正确的屏幕
【发布时间】:2021-04-24 17:58:34
【问题描述】:

我希望 BottomNavigationBar 保持不变,并将用户发送到不同的屏幕,具体取决于他们选择的索引以及在 BottomNavigationBar 上突出显示的索引。

我尝试这样做的方法是根据BottomNavigationBar() 的当前选定索引更改Scaffold 的主体值。我可以突出显示 BottomNavigationBar() 的选定索引,一旦它被选中,但正文没有路由到适当的小部件。

BottomNavBaronTap: 引用的当前方法正确突出显示所选索引,但未路由到正确的小部件。

我的BottomNavBar 中有一个未使用的方法 (_switchScreen)。将此作为onTap: 的值插入BottomNavBar() 会适当地路由到正确的屏幕,但随后我必须在每个视图上重建BottomNavBar,并且在BottomNavBar 后面无法访问NavModel 中引用的BottomNavBar (导航模型)。

这是我的BottomNavBar()

import 'package:flutter/material.dart';

import '../screens/Add_Media_Screen.dart';
import '../screens/Profile_Screen.dart';
import '../screens/Venture_Feed_Screen.dart';
   
class BottomNavBar extends StatefulWidget {
  @override
  _BottomNavBarState createState() => _BottomNavBarState();
}

class _BottomNavBarState extends State<BottomNavBar> {
  int _selectedIndex = 0;

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

  void _switchScreen(index) {
    switch (index) {
      case 0:
        Navigator.pushNamed(context, VentureFeedScreen.routeName);
        break;
      case 1:
        Navigator.pushNamed(context, ProfileScreen.routeName);
        break;
      case 2:
        Navigator.pushNamed(context, AddMediaScreen.routeName);
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Theme(
      data: ThemeData(
        primaryColor: Color(0xff84d1da),
        accentColor: Color(0xff62c2a2),
      ),
      child: BottomNavigationBar(
        selectedItemColor: Color(0xff84d1da),
        unselectedItemColor: Colors.grey,
        type: BottomNavigationBarType.fixed,
        items: const <BottomNavigationBarItem>[
          //Index 0
          BottomNavigationBarItem(
            icon: Icon(
              Icons.explore,
            ),
            label: 'Discover',
          ),
          //Index 1
          BottomNavigationBarItem(
            icon: Icon(
              Icons.account_circle,
              // color: Color(0xff84d1da),
            ),
            label: 'Profile',
            // backgroundColor: Color(0xff84d1da),
          ),
          //Index 2
          BottomNavigationBarItem(
            icon: Icon(
              Icons.add_circle_outline,
            ),
            label: 'Add Media',
          ),
        ],
        currentIndex: _selectedIndex,
        onTap: _onItemTapped,
      ),
    );
  }
}

这里是NavModel

import 'package:flutter/material.dart';

import '../screens/Profile_Screen.dart';
import '../screens/Venture_Feed_Screen.dart';
import '../screens/Add_Media_Screen.dart';

import '../widgets/BottomNavBar.dart';

class NavModel extends StatefulWidget {
  static const routeName = '/nav-model';
  @override
  _NavModelState createState() => _NavModelState();
}

class _NavModelState extends State<NavModel> {
  int _currentIndex = 0;

  final tabs = [
    VentureFeedScreen(),
    ProfileScreen(),
    AddMediaScreen(),
  ];

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: tabs[_currentIndex],
        bottomNavigationBar: BottomNavBar(),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart bottomnavigationview flutter-scaffold


    【解决方案1】:

    我认为您要完成的是 PageView 类的行为,对吗?将 PageView 作为脚手架的主体,并将 tabs 作为子级传递给 PageView。

    【讨论】:

    • 不完全。 PageView 启用轮播类型的操作。我试图让 BottomNavBar 控制导航。通过点击“发现”(索引 0)我被路由到 VentureFeedScreen(),点击“个人资料”(索引 1)我被路由到 ProfileScreen(),点击“添加媒体”(索引 2)我路由到AddMediaScreen()
    • 如果您不想要轮播式 UI,AnimatedSwitcher 应该可以解决问题,但这并没有使用 Navigator。如果您真的想使用导航器进行路由,我想您应该为每个页面定义一个底部导航栏并进行自定义路由转换,使其看起来好像只有脚手架的主体在变化,而不是底部导航栏(FadeTransition 可能会这样做)
    【解决方案2】:

    在这种情况下,将其拆分为两个不同的类是行不通的。在Scaffoldbody: 属性的NavModel() 类中,我试图根据静态索引值为0 的_currentIndex 更新tabs 列表的值。我认为通过调用BottomNavBar() 类并将onTap: 值设置为根据_onItemTapped 方法更新,它将根据BottomNavBar 类中_onItemTapped 方法中定义的内容更新body: 值。这是不正确的。

    代码运行正常,正如我定义的那样:Scaffold 的 body: tabs[_currentIndex] 调用了正确的逻辑 - 在选项卡列表的 0 索引处显示项目。当发生这种情况时,BottomNavBar 的索引正在更新以反映正确的用户选择的索引和值,从而导致混淆为什么 BottomNavBar 选择的索引正在更新而 Scaffold 的正文保持不变。

    这是正确的代码:

    class BottomNavBar extends StatefulWidget {
      static const routeName = '/navigator-model';
      @override
      _BottomNavBarState createState() => _BottomNavBarState();
    }
    
    class _BottomNavBarState extends State<BottomNavBar> {
      int _selectedIndex = 0;
    
      void _onItemTapped(int index) {
        setState(() {
          _selectedIndex = index;
        });
      }
    
      final List<Widget> tabs = [
        VentureFeedScreen(),
        ProfileScreen(),
        AddMediaScreen(),
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: tabs.elementAt(_selectedIndex),
          bottomNavigationBar: BottomNavigationBar(
            selectedItemColor: Color(0xff84d1da),
            unselectedItemColor: Colors.grey,
            type: BottomNavigationBarType.fixed,
            items: const <BottomNavigationBarItem>[
              //Index 0
              BottomNavigationBarItem(
                icon: Icon(
                  Icons.explore,
                ),
                label: 'Discover',
              ),
              //Index 1
              BottomNavigationBarItem(
                icon: Icon(
                  Icons.account_circle,
                  // color: Color(0xff84d1da),
                ),
                label: 'Profile',
                // backgroundColor: Color(0xff84d1da),
              ),
              //Index 2
              BottomNavigationBarItem(
                icon: Icon(
                  Icons.add_circle_outline,
                ),
                label: 'Add Media',
              ),
            ],
            currentIndex: _selectedIndex,
            onTap: _onItemTapped,
          ),
        );
      }
    }
    

    但是,我还没有看到 BottomNavBar 是否会持续导航到另一个屏幕(尚未构建该功能)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-04
      • 2020-10-11
      • 1970-01-01
      • 2019-09-17
      • 1970-01-01
      • 2021-09-12
      • 1970-01-01
      相关资源
      最近更新 更多