Flutter Bottom Navigation Bar - Best Practice Question

Viewed 677

I am pretty new to Flutter. I want to develop a Application with a Bottom Navigation Bar. But I don't really know what is the best way of Navigation. I made a custom Version of this Tutorial: https://medium.com/flutter/getting-to-the-bottom-of-navigation-in-flutter-b3e440b9386

What I did until now was:

  • Created a Main Widget with a Scaffold with a BottomNavigationBar
  • Everytime the index is changing I change the child Property of the Scaffold
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: MainWidget()
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class MainWidget extends StatefulWidget {
  @override
  _MainWidgetState createState() => _MainWidgetState();
}

/// This is the private State class that goes with MyStatefulWidget.
class _MainWidgetState extends State<MainWidget> {

  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
            top: false,
            child: IndexedStack(
              index: _selectedIndex,
              children: allDestinations.map<Widget>((Destination destination) {
                return DestinationView(destination: destination);
              }).toList(),
            )
        ),
        bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          selectedItemColor: Colors.blue,
          currentIndex: _selectedIndex,
          onTap: (int index) {
            setState(() {
              _selectedIndex = index;
            });
          },
          items: allDestinations.map((Destination destination) {
            return BottomNavigationBarItem(
                icon: Icon(destination.icon),
                label: destination.title
            );
          }).toList(),
        )
    );
  }
}

enum DestinationType {
  Page1,
  Page2,
  Page3,
  Page4,
  Page5
}

class Destination {
  const Destination(this.type, this.title, this.icon);
  final DestinationType type;
  final String title;
  final IconData icon;
}

const List<Destination> allDestinations = <Destination>[
  Destination(DestinationType.Page1, 'Page1', Icons.lightbulb),
  Destination(DestinationType.Page2, 'Page2', Icons.search),
  Destination(DestinationType.Page3, 'Page3', Icons.attach_money),
  Destination(DestinationType.Page4, 'Page4', Icons.calendar_today_outlined),
  Destination(DestinationType.Page5, 'Page5', Icons.settings)
];
  • I return a DestinationView where I am checking what Destination should be built.
class DestinationView extends StatefulWidget {
  const DestinationView({Key key, this.destination}) : super(key: key);

  final Destination destination;

  @override
  _DestinationViewState createState() => _DestinationViewState();
}

class _DestinationViewState extends State<DestinationView> {
  @override
  Widget build(BuildContext context) {
    switch (widget.destination.type) {
      case DestinationType.Page1:
        return Page1Destination(destination: widget.destination);
      case DestinationType.Page2:
        return Page2Destination(destination: widget.destination);
      case DestinationType.Page3:
        return Page3();
      case DestinationType.Page4:
        return Page4();
      case DestinationType.Page5:
        return Page5();
    }
  }
}
  • If I have a Part where I want to have Navigation in only this Part, I create a Navigator and define routes:
class Page1Destination extends StatefulWidget {
  const Page1Destination({Key key, this.destination}) : super(key: key);

  final Destination destination;

  @override
  _Page1DestinationState createState() => _Page1DestinationState();
}

class _Page1DestinationState extends State<Page1Destination> {
  @override
  Widget build(BuildContext context) {
    return Navigator(
      onGenerateRoute: (RouteSettings settings) {
        return MaterialPageRoute(
          settings: settings,
          builder: (BuildContext context) {
            switch(settings.name) {
              case '/':
                return Page1Home(destination: widget.destination);
              case '/list':
                return Page1List();
              case '/settings':
                return Page1Settings(destination: widget.destination);
            }
          },
        );
      },
    );
  }
}
  • Inside these widgets I use Navigator.pushNamed and so on.
  • If the Tab/Page is only one widget. I only return a normal widget without any routes.
  • But if want to call a Widget in Page 1 with the route /list and a parameter from another page. I don't know how to do that.

I'm pretty sure there is a better way of handling that kind of Navigation. So maybe one of you knows how I can create a better Navigation-Handler.

0 Answers
Related