Home > OS >  Persisting BottomNavigationBar with changing AppBar
Persisting BottomNavigationBar with changing AppBar

Time:09-22

So I'm creating an screen with 5 BottomNavigationBarItem(s) that would ideally persist, while the AppBar changes according to the design. Here's my code:

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

Upon Login, they land on the 'Explore' screen but was wondering if this structure is ideal. What I was thinking was a 'common' scaffold for a blank body, 5 BottomNavigationBarItems and a changing AppBar Menu items (for instance, "Messaging" has "Conversations" and "Appointments" AppBar items)

How do we go about properly coding this.

enter image description here

Here is a Sample for the "Messaging" BottomNavigationBarItem.

enter image description here

CodePudding user response:

One possible approach:

  1. Create one Scaffold with your BottomNavigationBar.
  2. Use an IndexedStack (see here) as the body of your Scaffold.
  3. Create the different bodies (Explore, Messaging etc.) and use setState when user clicks on one of your BottomNavigationBarItems and change the current index for IndexedStack.
  4. Also create different AppBar widgets for the different bodies (for example in an array), assign it to the Scaffold based on a state value and in the previously mentioned setState update also its value.

This will work until you can or want to keep all these widgets in the same Stateless Widget class. Chances are good that later you will want to separate them into different classes so that your code is more easy to read. In that case you can use ChangeNotifier, ChangeNotifierProvider and Consumer to communicate state changes between your widgets, as explained here.

  • Related