Home > Enterprise >  Dynamic BottomNavigationBarItems throwing error 'items.length >= 2': is not true
Dynamic BottomNavigationBarItems throwing error 'items.length >= 2': is not true

Time:12-21

I want to create a dynamic BottomNavigationBar so that for each screen I can pass the icons/routes I need on that screen. My bottom.dart file looks like this:

import 'package:flutter/material.dart';

class BottomBar extends StatefulWidget {
  final List routesToShow;

  BottomBar({Key? key, required this.routesToShow}) : super(key: key);

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

class _BottomBar extends State<BottomBar> {
  final Map allBottomMenus = {
    'home': {'icon': Icon(Icons.home), 'title': Text('Home'), 'route': '/homepage'},
    'profile': {'icon': Icon(Icons.verified_user), 'title': Text('Profile'), 'route':     '/profile'},
    'info': {'icon': Icon(Icons.info_outline), 'title': Text('Info'), 'route': '/info'},
    'previousScreen': {'icon': Icon(Icons.backspace), 'title': Text('Back'), 'route': ''},
  };

  List<BottomNavigationBarItem> bottomNavigationItems = [];

  void _buildBottomNavigation() {
    widget.routesToShow.forEach((route) {
      if (allBottomMenus.containsKey(route)) {
        bottomNavigationItems.add(BottomNavigationBarItem(
          icon: allBottomMenus[route]['icon'],
          label: allBottomMenus[route]['title'],
        ));
      }
    });
  }

  @override
  void initState() {
    super.initState();
    _buildBottomNavigation();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      items: List.of(bottomNavigationItems),
      onTap: (int index) {
        print(index);
      },
    );
  }
}

and in the homepage, I call this widget like following:

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

  @override
  Widget build(BuildContext context) {
    final routesToShow = List.filled(3, ['homepage', 'info', 'profile']);

    return Scaffold(
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            children: [
              buildHeader(),
              const SizedBox(height: 32.0),
            ],
          ),
        ),
      ),
      bottomNavigationBar: BottomBar(routesToShow: routesToShow),
    );
  }
}

But I get an error saying:

Failed assertion: line 307 pos 15: 'items.length >= 2': is not true.

Seems like the widget is never executed as there are no items. Any help will be appreciated.

CodePudding user response:

There were two problems with your code, first this line:

final routesToShow = List.filled(3, ['homepage', 'info', 'profile']);

it makes a 2D list, therefore you can not retrieve desired data from it with your forEach method; so replace it with:

  final routesToShow = ['homepage', 'info', 'profile'];

the second problem was your map, BottomNavigationBar expects to find a String for label not a Text widget, so replace it with:

final Map allBottomMenus = {
    'home': {'icon': Icon(Icons.home), 'title': 'Home', 'route': '/homepage'},
    'profile': {
      'icon': Icon(Icons.verified_user),
      'title': 'Profile',
      'route': '/profile'
    },
    'info': {
      'icon': Icon(Icons.info_outline),
      'title': 'Info',
      'route': '/info'
    },
    'previousScreen': {
      'icon': Icon(Icons.backspace),
      'title': 'Back',
      'route': ''
    },
  };
  • Related