skip to Main Content

Hey there I’m pretty new to flutter. I’m trying to get my BottomNavigationBar running. I’m using the bloc package for state changes, sending out an event when tapping on a BottomNavigationBar. I have 2 BlocConsumers… 1 in my root page to swap out the page and 1 BlocConsumer in my CustomBottomNavBar widget. When testing they separately (so when only having 1 BlocConsumer listening to my event) it works. Also when I have both BlocConsumers the listeners work, I see my custom message printed to the console, but the BottomNavigationBar for some reason is not rebuilding. Any idea why that is? Thanks a lot for your help!

VideoLink to proof that the Bottom Bar does not rebuild:

https://youtu.be/bgxWTxGCZ5Q

root.dart:

import 'package:auto_route/auto_route.dart';
import 'package:cook_meet_repeat/application/auth/auth/auth_bloc.dart';

import 'package:cook_meet_repeat/application/root/root_bloc.dart';
import 'package:cook_meet_repeat/presentation/custom_bottom_nav_bar.dart';
import 'package:cook_meet_repeat/presentation/root/events/events_page.dart';
import 'package:cook_meet_repeat/presentation/root/host_events/host_events.dart';
import 'package:cook_meet_repeat/presentation/routes/router.gr.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../constants/icons.dart';

@RoutePage()
class RootPage extends StatefulWidget {
  const RootPage({super.key});

  @override
  State<RootPage> createState() => _RootPageState();
}

class _RootPageState extends State<RootPage> {
  final pages = [EventsPage(), HostEventsPage(), Placeholder(), Placeholder(), Placeholder()];
  var selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return MultiBlocListener(
      listeners: [
        BlocListener<AuthBloc, AuthState>(listener: (context, state) {
          if (state is AuthStateAuthenticated) {
            AutoRouter.of(context).push(const SignupRoute());
          }
        }),
      ],
      child: BlocConsumer<RootBloc, RootBottomNavigationState>(
          listener: (context, state) {
        selectedIndex = state.selectedIndex;
        print("RootPage selectedIndex $selectedIndex");
      }, builder: (context, state) {
        return Scaffold(
            body: pages[selectedIndex],
            bottomNavigationBar: CustomBottomNavBar());
      }),
    );
  }
}

custom_bottom_nav_bar.dart:

import 'package:cook_meet_repeat/application/root/root_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class CustomBottomNavBar extends StatelessWidget {
  const CustomBottomNavBar({super.key});

  @override
  Widget build(BuildContext context) {
    final themeData = Theme.of(context);

    int selectedIndex = 0;

    return BlocConsumer<RootBloc, RootBottomNavigationState>(
        listener: (context, state) {
          selectedIndex = state.selectedIndex;
          print("CustomBottomNavBar selectedIndex: $selectedIndex");
        },
      builder: (context, state) {
        return BottomNavigationBar(
            type: BottomNavigationBarType.fixed,
            backgroundColor: themeData.primaryColor,
            unselectedFontSize: 14,
            items: const <BottomNavigationBarItem>[
              BottomNavigationBarItem(
                icon: Icon(Icons.set_meal_rounded),
                label: 'Events',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.groups),
                label: 'Community',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.add_circle),
                label: 'Host',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.message_rounded),
                label: 'Messages',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.person_4_rounded),
                label: 'Profile',
              ),
            ],
            currentIndex: selectedIndex,
            selectedItemColor: Colors.amber[800],
            selectedFontSize: 14,
            onTap: (index) {
              print("tapped on: $index");

              BlocProvider.of<RootBloc>(context).add(
                  RootBottomNavigationPressed(selectedIndex: index));
            }
        );
      });
  }
}

My Console Log which proofs that the listeners work

I/flutter (17333): tapped on: 2
I/flutter (17333): RootPage selectedIndex 2
I/flutter (17333): CustomBottomNavBar selectedIndex: 2
D/EGL_emulation(17333): app_time_stats: avg=11.14ms min=5.94ms max=45.80ms count=57
I/flutter (17333): tapped on: 3
I/flutter (17333): RootPage selectedIndex 3
I/flutter (17333): CustomBottomNavBar selectedIndex: 3

Tested the BlocConsumers seperately… they work separately

2

Answers


  1. In CustomBottomNavBar class:

    Don’t define selectedIndex = 0 in build. It will be re assign to 0 when build get called. Just get selectedIndex from state of BlocConsumer builder(context, state).

    In your case selectedIndex = state.selectedIndex is unnecessary. Just use BlocBuilder and you can remove listener block

    Hope it can help you.

    Login or Signup to reply.
  2. Just remnove this line:

    int selectedIndex = 0;
    

    You don’t need store this value in widget because you should react on it changes getting it from your state:

    builder: (context, state) {
            final selectedIndex = state.selectedIndex;
            return BottomNavigationBar(
                type: BottomNavigationBarType.fixed,
                ...
                currentIndex: selectedIndex,
                ...
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search