Most apps have a bottom navigation bar, which can be used to switch between different pages. The BottomNavigationBar component is provided in the Flutter for bottom navigation. This article describes how to build the most common App page framework using the BottomNavigationBar and IndexedStack.

The final result is shown in the figure above, with a navigation bar at the top and four ICONS at the bottom. Click the corresponding icon to jump to the corresponding page.

Icon to

This routine needs 4 ICONS, 2 colors, you can find the iconfont icon you need to download different colors to use. Then in assets in pubspec.yaml, specify the directory where the material is. Note that for PNG files, you can specify the entire directory, but for JPG files, you need to specify both the file name and suffix.

BottomNavigationBar profile

The constructor of BottomNavigationBar is as follows:

BottomNavigationBar({
    Key? key,
    required this.items,
    this.onTap,
    this.currentIndex = 0.this.elevation,
    this.type,
    Color? fixedColor,
    this.backgroundColor,
    this.iconSize = 24.0,
    Color? selectedItemColor,
    this.unselectedItemColor,
    this.selectedIconTheme,
    this.unselectedIconTheme,
    this.selectedFontSize = 14.0.this.unselectedFontSize = 12.0.this.selectedLabelStyle,
    this.unselectedLabelStyle,
    this.showSelectedLabels,
    this.showUnselectedLabels,
    this.mouseCursor,
  })
Copy the code

The commonly used attributes are:

  • Items: and the corresponding array of page components
  • CurrentIndex: Indicates the page number displayed by default
  • Type: Component type, which is enumerated by BottomNavigationBarType, can be fixed or shifting. Fixed is the fixed position of the icon, while fixed will have a drifting effect after clicking the icon of rat. You can try it in practice. Generally, fixed is more used.
  • OnTap: The event after a click, which is typically used to update status data to update the page.

Other properties are used to control the style, you can set the icon size, theme color, font and other parameters according to the actual need.

Build the project page structure

Dart, message. Dart, category. Dart, and mine. Dart, corresponding to the four pages of dynamic, message, category browsing, and personal center respectively. So far, the four pages are simple, just displaying the words “Island coder” in the middle of the page. The code is similar. Take dynamic as an example:

import 'package:flutter/material.dart';

class DynamicPage extends StatelessWidget {
  const DynamicPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('island'),),); }}Copy the code

Note that the Scaffold here has no AppBar because it already has one on the home page and there will be two more.

Second, create a new home page to manage four business pages, named app.dart. App. dart uses the BottomNavigationBar to manage the switching of four business pages.

import 'package:flutter/material.dart';
import 'dynamic.dart';
import 'message.dart';
import 'category.dart';
import 'mine.dart';

class AppHomePage extends StatefulWidget {
  AppHomePage({Key key}) : super(key: key);

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

class _AppHomePageState extends State<AppHomePage> {
  int _index = 0;

  List<Widget> _homeWidgets = [
    DynamicPage(),
    MessagePage(),
    CategoryPage(),
    MinePage(),
  ];

  void _onBottomNagigationBarTapped(index) {
    setState(() {
      _index = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Island Coders'),
      ),
      body: IndexedStack(
        index: _index,
        children: _homeWidgets,
      ),
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: _index,
        onTap: _onBottomNagigationBarTapped,
        items: [
          _getBottomNavItem(
              'dynamic'.'images/dynamic.png'.'images/dynamic-hover.png'.0),
          _getBottomNavItem(
              'message'.'images/message.png'.'images/message-hover.png'.1),
          _getBottomNavItem(
              'Browse by Category'.'images/category.png'.'images/category-hover.png'.2),
          _getBottomNavItem(
              'Personal center'.'images/mine.png'.'images/mine-hover.png'.3),,),); } BottomNavigationBarItem _getBottomNavItem(String title, String normalIcon, String pressedIcon, int index) {
    return BottomNavigationBarItem(
      icon: _index == index
          ? Image.asset(
              pressedIcon,
              width: 32,
              height: 28,
            )
          : Image.asset(
              normalIcon,
              width: 32,
              height: 28, ), label: title, ); }}Copy the code

There are two key points here. One is the use of IndexedStack, which is a container that manages the page display hierarchy. Use the index property to determine which page in the current container is at the top. The page in the container is set by the children property, which requires an array of widgets. Therefore, the logic is that when the icon in the BottomNavigationBar is clicked, the corresponding click event will call back to the method specified by the onTap property, passing the current click index value to the callback function, so you can control the page hierarchy of the IndexedStack in this way.

Finally, we use the status variable _index to store the index value of the currently displayed page in IndexedStatck, and then use setState to update the status variable _index in the callback function to refresh the current page after the BottomNavigationBar icon click event occurs.

Simplify the entrance

The main.dart is an entry file that should do basic configuration and global initialization without any business code, so it can be simplified by loading the home page from the main method. This way you can make the main.dart file simple. This is where development needs to be careful, stripping out the unrelated code and aggregating the relevant code, the so-called “high cohesion, low coupling” principle.

import 'package:flutter/material.dart';
import 'app.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'the App framework', theme: ThemeData( primarySwatch: Colors.blue, ), home: AppHomePage(), ); }}Copy the code

Code reuse

In this case, the BottomNavigationBar element is built using the getbottomnavitem method to improve code reuse and maintainability. You can also avoid excessive elements and nesting in the build method of the component builds of Flutter, which can affect the readability of the code.