Search code examples
flutterbottomnavigationview

Bottom Navbar takes more height in some devices in Flutter


I'm working on a BottomNavigationBar in my Flutter app, but I noticed, it takes more height in some phones, like some Iphones,Samsung Galaxy S23, etc. I try to put a Container or a SizeBox with pre-defined height but nothing changes.Anyone have a solution for it?.

Here's the code:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: tdWhite,
      bottomNavigationBar: Padding(
        padding: const EdgeInsets.all(8),
        child: ClipRRect(
            borderRadius: BorderRadius.circular(100),
            child: BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              backgroundColor: tdWhiteNav,
              showSelectedLabels: false,
              showUnselectedLabels: false,
              onTap: (int newIndex) {},
              items:const [
                BottomNavigationBarItem(
                  icon:  Icon(MyFlutterApp.home, color: tdIconColor),
                  label: '',
                ),
                BottomNavigationBarItem(
                  icon:  Icon(MyFlutterApp.ticket, color: tdIconColor, size: 40),
                  label: '',
                ),
                BottomNavigationBarItem(
                  icon:   Icon(MyFlutterApp.group_168, color: tdBlack, size: 40),
                  label: '',
                ),
                BottomNavigationBarItem(
                  icon:  Icon(MyFlutterApp.profile, color: tdIconColor),
                  label: '',
                ),

And here's a picture of what it looks like: enter image description here


Solution

  • This isn't an issue for most navigation bars as it's expected that they simply go to the bottom. However, your case does make it a bit more difficult.

    What you need to do is remove the viewPadding that the BottomNavigationBar uses to determine how much padding to add to its bottom.

    This should do it:

    return Scaffold(
      ...
      bottomNavigationBar: Builder(
        builder: (context) {
          final mediaQuery = MediaQuery.of(context);
          return MediaQuery(
            data: mediaQuery.removeViewPadding(
              removeBottom: true,
            ),
            child: Padding(
              padding: EdgeInsets.only(
                top: 8,
                right: 8,
                left: 8,
                bottom: 8 + mediaQuery.viewPadding.bottom,
              ),
              child: ClipRRect(
                 /// your code as it is here
              ),
            ),
          );
        }
      ),
    );
        
    

    This makes it so that any widgets requesting the viewPadding (i.e. the BottomNavigationBar) will see zero instead of whatever was in .viewPadding.bottom. I also re-added the padding outside of the navigation bar such that it won't be covered up with some sort of UI.

    I'd advise refactoring that all into a widget in which case you won't need the Builder. That was used so that the context being accessed is the context of the scaffold rather than the widget, in case the scaffold does any modifications to the MediaQuery - if the mediaQuery were retrieved from the context outside the scaffold then doing this could overwrite any changes.

    One thing to be careful of is that this has the slight possibility of making other things the scaffold does (like showing a snackbar) not look right - you should test that out if you're going to use them, and if it does break something you may have to wrap the entire scaffold in the padding.

    One more thing - BottomNavigationBar has been replaced with NavigationBar and that is recommended for new applications. I'm not sure if it uses the exact same property, it may use MediaQuery.padding instead of MediaQuery.viewPadding.