flutterdartbottom-navigation-bar

Change size of BottomNavigationBar onTap?


I am trying to add a BottomNavigationBar that whenever you tap the screen (tapping on a map in my instance) or swipe down, its size becomes smaller and some items in it get removed.

For example:

Concept

I am trying to replicate the BNB of the app Citymapper


Solution

  • One way to achieve this is by adding a transparent layer above the details attached to the bottom navigation bar. In that portion of the UI, you can use GestureDetector to handle gestures but this has to be designed using Stack. Here is a minimal code.

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MaterialApp(
        home: App(),
      ));
    }
    
    class App extends StatefulWidget {
      const App({super.key});
    
      @override
      State<App> createState() => _AppState();
    }
    
    class _AppState extends State<App> {
      bool isExpanded = true;
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            backgroundColor: Colors.amber,
            body: Stack(
              children: [
                ///Your map view goes at the bottom of the stack
                const Center(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.map),
                      Text("Map view"),
                    ],
                  ),
                ),
                ///Your custom bottom navigation bar
                Align(
                  alignment: Alignment.bottomCenter,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      if (isExpanded)
                        Expanded(
                          child: ExpandedView(onTap: () {
                            setState(() {
                              isExpanded = false;
                            });
                          }),
                        ),
                      BottomNavigationBar(
                        onTap: (_) {
                          setState(() {
                            isExpanded = true;
                          });
                        },
                        elevation: 0,
                        items: const [
                          BottomNavigationBarItem(
                              icon: Icon(Icons.local_taxi_outlined), label: "Taxi"),
                          BottomNavigationBarItem(
                              icon: Icon(Icons.train_outlined), label: "Train")
                        ],
                      ),
                    ],
                  ),
                )
              ],
            ));
      }
    }
    
    class ExpandedView extends StatelessWidget {
      final VoidCallback onTap;
      const ExpandedView({super.key, required this.onTap});
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            Expanded(
              child: GestureDetector(
                //handle other gesture callbacks
                onTap: onTap,
                child: Container(
                  color: Colors.transparent,
                ),
              ),
            ),
            Container(
              height: 150,
              width: MediaQuery.sizeOf(context).width,
              color: Colors.green,
            ),
          ],
        );
      }
    }