Show Bottom Modal Sheet above the Bottom Navigation Bar
H

3

9

Here in the below image I have added showModalBottomSheet on clicking on the item of "Bottom Navigation Bar", but the BottomNavigationBar is hidden by the modal sheet, So I want to make it visible even the bottom sheet is present. Can anyone please anyone help me out.

enter image description here

This is my bottom navigation code:

Widget _bottomNavigationBar() {
  return BottomNavigationBar(
      type: BottomNavigationBarType.fixed,
      key: scaffoldState,
      items: const <BottomNavigationBarItem>[
        BottomNavigationBarItem(
          icon: Icon(Icons.home),
          label: 'Home',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.branding_watermark_outlined),
          label: 'Brands',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.category),
          label: 'Category',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.person),
          label: 'Profile',
        )
      ],
      currentIndex: _selectedIndex,
      selectedItemColor: AppColors.blue,
      onTap: (newIndex) => {
            if (newIndex == 1)
              {showBrandsBottomSheet(context)}
            else if (newIndex == 2)
              {showCategoryBottomSheet(context)}
            else
              {
                setState(() {
                  _selectedIndex = newIndex;
                })
              }
          });
}

Here is my code for bottom model sheet:

showBrandsBottomSheet(BuildContext context) {
  return showModalBottomSheet<void>(
    shape: const RoundedRectangleBorder(
      borderRadius: BorderRadius.only(
          topLeft: Radius.circular(15.0), topRight: Radius.circular(15.0)),
    ),
    context: context,
    useRootNavigator: true,
    isScrollControlled: true,
    builder: (BuildContext _) {
      return Container(
        color: Colors.white,
        height: MediaQuery.of(context).size.height / 2,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.only(right: 5, top: 3),
                child: GestureDetector(
                  onTap: () {
                    Navigator.pop(context);
                  },
                  child: const Align(
                      alignment: Alignment.topRight,
                      child: Icon(Icons.close)),
                ),
              ),
              Container(
                color: Colors.white,
                height: 350,
                child: ListView.builder(
                  key: Key('builder ${_selected.toString()}'), //a
                  scrollDirection: Axis.vertical,
                  // shrinkWrap: true,
                  // physics: NeverScrollableScrollPhysics(),
                  itemCount: brandList.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Theme(
                        data: Theme.of(context)
                            .copyWith(dividerColor: Colors.white),
                        child: ExpansionTile(
                          // tilePadding: const EdgeInsets.all(0),
                          key: Key(index.toString()), //attention
                          initiallyExpanded: index == _selected, //attention
                          collapsedIconColor: Colors.blue,
                          iconColor: Colors.blue,
                          backgroundColor: Colors.white,
                          title: Text(
                            brandList[index],
                            style: const TextStyle(
                                fontSize: 13.0,
                                color: Colors.black,
                                fontWeight: FontWeight.w600),
                          ),
                          children: <Widget>[
                            Container(
                              color: Colors.blue[50],
                              child: Column(
                                children: _buildExpandableBrands(brandList),
                              ),
                            ),
                          ],
                          onExpansionChanged: ((newState) {
                            if (newState) {
                              setState(() {
                                const Duration(seconds: 20000);
                                _selected = index;
                              });
                            } else {
                              setState(() {
                                _selected = -1;
                              });
                            }
                          }),
                        ));
                  },
                ),
              ),
            ],
          ),
        ),
      );
    },
  );
}
Harmonicon answered 25/4, 2022 at 7:52 Comment(0)
H
1

Finally, this question helped me in getting this done.

Here is my working code:

Widget _bottomNavigationBar() {
    return BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        key: scaffoldState,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.branding_watermark_outlined),
            label: 'Brands',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.category),
            label: 'Category',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          )
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: AppColors.blue,
        onTap: (newIndex) => {
              if (newIndex == 1)
                {
                  _scaffoldKey.currentState?.showBottomSheet((_) => Container(
                        child: showBrandsBottomSheet(),
                      ))
                }
              else if (newIndex == 2)
                {
                  {
                    _scaffoldKey.currentState?.showBottomSheet((_) => Container(
                          child: showCategoryBottomSheet(),
                        ))
                  }
                }
              else
                {
                  setState(() {
                    _selectedIndex = newIndex;
                  })
                }
            });
  }

showBrandsBottomSheet:

showBrandsBottomSheet() {
    return Container(
      color: Colors.white,
      height: MediaQuery.of(context).size.height / 2,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(right: 5, top: 3),
              child: GestureDetector(
                onTap: () {
                  Navigator.pop(context);
                },
                child: const Align(
                    alignment: Alignment.topRight, child: Icon(Icons.close)),
              ),
            ),
            Container(
              color: Colors.white,
              height: 350,
              child: ListView.builder(
                key: UniqueKey(),
                scrollDirection: Axis.vertical,
                itemCount: brandList.length,
                itemBuilder: (BuildContext context, int index) {
                  cardKeyList.add(GlobalKey(debugLabel: "index :$index"));
                  return Theme(
                      data: Theme.of(context)
                          .copyWith(dividerColor: Colors.white),
                      child: ExpansionTileCard(
                        key: cardKeyList[index],
                        initiallyExpanded: false,
                        title: Text(
                          brandList[index],
                          style: const TextStyle(
                              fontSize: 13.0,
                              color: Colors.black,
                              fontWeight: FontWeight.w600),
                        ),
                        children: <Widget>[
                          Container(
                            color: Colors.blue[50],
                            child: Column(
                              children: _buildExpandableBrands(brandList),
                            ),
                          ),
                        ],
                        onExpansionChanged: (value) {
                          if (value) {
                            Future.delayed(const Duration(milliseconds: 200),
                                () {
                              for (var i = 0; i < cardKeyList.length; i++) {
                                if (index != i) {
                                  cardKeyList[i].currentState?.collapse();
                                }
                              }
                            });
                          }
                        },
                      ));
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

Now it is started showing above the bottom navigation.

Harmonicon answered 25/4, 2022 at 12:34 Comment(1)
But still there is a problem with this solution, the screen background is not getting blurred.Harmonicon
N
44

set useRootNavigator=true.This will display model sheet above all other content.

showModalBottomSheet(
     context: context,
     isScrollControlled: true,
     useRootNavigator: true,
     builder: (context) {
     return BottomBarView(
     );
});
Nonappearance answered 25/4, 2022 at 8:25 Comment(2)
Tried but not working, please check my updated question.Harmonicon
@Gursewak Singh, what do I do if I want to select a new route from the bottom sheet which is meant to show the bottom navigator again? How can I get bottom navigator back for this new route?Schnorrer
H
1

Finally, this question helped me in getting this done.

Here is my working code:

Widget _bottomNavigationBar() {
    return BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        key: scaffoldState,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.branding_watermark_outlined),
            label: 'Brands',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.category),
            label: 'Category',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: 'Profile',
          )
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: AppColors.blue,
        onTap: (newIndex) => {
              if (newIndex == 1)
                {
                  _scaffoldKey.currentState?.showBottomSheet((_) => Container(
                        child: showBrandsBottomSheet(),
                      ))
                }
              else if (newIndex == 2)
                {
                  {
                    _scaffoldKey.currentState?.showBottomSheet((_) => Container(
                          child: showCategoryBottomSheet(),
                        ))
                  }
                }
              else
                {
                  setState(() {
                    _selectedIndex = newIndex;
                  })
                }
            });
  }

showBrandsBottomSheet:

showBrandsBottomSheet() {
    return Container(
      color: Colors.white,
      height: MediaQuery.of(context).size.height / 2,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.only(right: 5, top: 3),
              child: GestureDetector(
                onTap: () {
                  Navigator.pop(context);
                },
                child: const Align(
                    alignment: Alignment.topRight, child: Icon(Icons.close)),
              ),
            ),
            Container(
              color: Colors.white,
              height: 350,
              child: ListView.builder(
                key: UniqueKey(),
                scrollDirection: Axis.vertical,
                itemCount: brandList.length,
                itemBuilder: (BuildContext context, int index) {
                  cardKeyList.add(GlobalKey(debugLabel: "index :$index"));
                  return Theme(
                      data: Theme.of(context)
                          .copyWith(dividerColor: Colors.white),
                      child: ExpansionTileCard(
                        key: cardKeyList[index],
                        initiallyExpanded: false,
                        title: Text(
                          brandList[index],
                          style: const TextStyle(
                              fontSize: 13.0,
                              color: Colors.black,
                              fontWeight: FontWeight.w600),
                        ),
                        children: <Widget>[
                          Container(
                            color: Colors.blue[50],
                            child: Column(
                              children: _buildExpandableBrands(brandList),
                            ),
                          ),
                        ],
                        onExpansionChanged: (value) {
                          if (value) {
                            Future.delayed(const Duration(milliseconds: 200),
                                () {
                              for (var i = 0; i < cardKeyList.length; i++) {
                                if (index != i) {
                                  cardKeyList[i].currentState?.collapse();
                                }
                              }
                            });
                          }
                        },
                      ));
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

Now it is started showing above the bottom navigation.

Harmonicon answered 25/4, 2022 at 12:34 Comment(1)
But still there is a problem with this solution, the screen background is not getting blurred.Harmonicon
Y
0

i also faced the same issue i want to show modal bottom sheet but the sheet should not hide the bottom bar and I wanted to also display the buttons that showed the bottom sheet to enable and disable the bottom sheet so I used DraggableScrollableSheet in a stack widget which will show the button on the top of the bottom sheet

one thing to make sure that the minChidsize and the initialChildSize should be equal

 if (isShowBottomListSheet)
                      DraggableScrollableSheet(
                        initialChildSize: 0.3,
                        // Starts at 30% of screen height
                        minChildSize: 0.3,
                        // Minimum size when collapsed
                        maxChildSize: 1.0,
                        // Maximum size when fully expanded
                        builder: (context, scrollController) {
                          return Container(
                            decoration: BoxDecoration(
                              color: Colors.white,
                              borderRadius: BorderRadius.vertical(
                                  top: Radius.circular(20)),
                              boxShadow: [
                                BoxShadow(
                                    color: Colors.black26, blurRadius: 10)
                              ],
                            ),
                            child: ListView.builder(
                              controller: scrollController,
                              itemCount: 20, // Example list of items
                              itemBuilder: (context, index) {
                                return ListTile(
                                  title: Text('Item $index'),
                                );
                              },
                            ),
                          );
                        },
                      ),

Sample Image Link

Yucca answered 12/9 at 5:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.