【问题标题】:Persisting BottomNavigationBar with changing AppBar通过更改 AppBar 持久化 BottomNavigationBar
【发布时间】:2021-09-21 06:26:10
【问题描述】:

所以我正在创建一个具有 5 个BottomNavigationBarItem(s) 的屏幕,理想情况下会持续存在,而AppBar 会根据设计进行更改。这是我的代码:

class ExploreState extends State<ExploreScreen> {
  int _selectedIndexForBottomNavigationBar = 0;

  void _onItemTappedForBottomNavigationBar(int index) {
    setState(() {
      _selectedIndexForBottomNavigationBar = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new DefaultTabController(
      length: 3,
      child: new Scaffold(
        appBar: AppBar(
          bottom: ColoredTabBar(
            color: Colors.white,
            tabBar: TabBar(
              labelColor: Colors.grey[900],
              indicator: UnderlineTabIndicator(
                borderSide: BorderSide(color: kPrimaryColor, width: 2.0),
              ),
              tabs: <Widget>[
                Tab(text: "Job Posts"),
                Tab(
                  text: "Agencies",
                ),
                Tab(
                  text: "All Applicants",
                ),
              ],
            ),
          ),
          elevation: 0.7,
          centerTitle: true,
          title: Text(
            "Looking For",
            style: TextStyle(fontSize: 18),
          ),
          actions: <Widget>[
            Icon(Icons.search),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 5.0),
            ),
          ],
        ),
        body: TabBarView(
          children: <Widget>[
            Jobs(),
            Agencies(),
            Applicants(),
          ],
        ),
        bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          items: <BottomNavigationBarItem>[
            _bottomNavigationBarItem(
                AssetImage("assets/images/search-job.png"), 'Explore'),
            _bottomNavigationBarItem(
                AssetImage("assets/images/message.png"), 'Messaging'),
            _bottomNavigationBarItem(
                AssetImage("assets/images/forums.png"), 'Forums'),
            _bottomNavigationBarItem(
                AssetImage("assets/images/notifications.png"), 'Notifications'),
            _bottomNavigationBarItem(
                AssetImage("assets/images/profile.png"), 'Edit Profile'),
          ],
          currentIndex: _selectedIndexForBottomNavigationBar,
          selectedItemColor: kPrimaryColor,
          onTap: _onItemTappedForBottomNavigationBar,
          selectedFontSize: 0,
        ),
      ),
    );
  }

  BottomNavigationBarItem _bottomNavigationBarItem(
      AssetImage icon, String label) {
    return BottomNavigationBarItem(
      activeIcon: _navItemIcon(
          icon, label, [kPrimaryColor, kPrimaryWelcomeColor], Colors.white),
      icon: _navItemIcon(
          icon, label, [Colors.white, Colors.white], Color(0xFF4E5969)),
      label: "",
    );
  }

  Row _navItemIcon(AssetImage icon, String label, List<Color> backgrondColor,
      Color? foregroundColor) {
    return Row(
      children: [
        Expanded(
          child: Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.bottomLeft,
                end: Alignment.topRight,
                colors: backgrondColor,
                transform: GradientRotation(1.5),
              ),
            ),
            child: Padding(
              padding: const EdgeInsets.all(15.0),
              child: Column(
                children: [
                  ImageIcon(
                    icon,
                    size: 25,
                    color: foregroundColor,
                  ),
                  Text(
                    label,
                    style: TextStyle(color: foregroundColor, fontSize: 8),
                  )
                ],
              ),
            ),
          ),
        ),
      ],
    );
  }
}

class ColoredTabBar extends Container implements PreferredSizeWidget {
  ColoredTabBar({this.color = Colors.white, this.tabBar});

  final Color color;
  final TabBar? tabBar;

  @override
  Size get preferredSize => tabBar!.preferredSize;

  @override
  Widget build(BuildContext context) => Container(
        color: color,
        child: tabBar,
      );
}

登录后,他们登陆“探索”屏幕,但想知道这种结构是否理想。我在想的是一个用于空白正文、5 个 BottomNavigationBarItems 和不断变化的 AppBar 菜单项的“通用”脚手架(例如,“Messaging”具有“Conversations”和“Appointments”AppBar 项)

我们如何正确编码。

这是“消息传递”BottomNavigationBarItem 的示例。

【问题讨论】:

    标签: flutter dart flutter-layout


    【解决方案1】:

    一种可能的方法:

    1. 用您的BottomNavigationBar 创建一个Scaffold
    2. 使用IndexedStack (see here) 作为bodyScaffold
    3. 当用户点击您的BottomNavigationBarItems 之一并更改IndexedStack 的当前索引时,创建不同的正文(探索、消息传递等)并使用setState
    4. 还为不同的主体创建不同的AppBar 小部件(例如在数组中),根据状态值将其分配给Scaffold,并在前面提到的setState 中更新其值。

    这将一直有效,直到您可以或想要将所有这些小部件保留在同一个无状态小部件类中。稍后您很有可能希望将它们分成不同的类,以便您的代码更易于阅读。在这种情况下,您可以使用 ChangeNotifier、ChangeNotifierProvider 和 Consumer 在您的小部件之间传达状态更改,如 explained here

    【讨论】:

    • 您也可以在不同的主体中实现您的选项卡,然后您不需要更新公共应用栏。这可能是一个更好的解决方案。
    • 谢谢!我已经将 BottomNavigation 实现为 TabBar(而不是更新它),然后在顶部使用不同的 TabBarViews,使用相同的 TabController 将小部件(有组织的探索、消息传递等及其主体和它们各自的顶部栏)分开。
    • 太好了,不客气。
    猜你喜欢
    • 2019-11-13
    • 2020-06-04
    • 1970-01-01
    • 2021-11-08
    • 2018-05-10
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多