💙

【Flutter】BottomNavigationBarの使い方、よくあるトラブルの対応

2024/03/06に公開

BottomNavigationBarは画面の下部にボタンを表示して画面を切り替えるためのウィジェット。

基本的な使い方

Scaffold内で使用することが一般的。以下のように記述することでBottomNavigationBarを表示できる。

class TestPage extends StatefulWidget {
  const TestPage({super.key});

  
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  // 選択中のアイテムindex
  int _currentIndex = 0;

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(),
      bottomNavigationBar: BottomNavigationBar(
        // 選択中のアイテムindex
        currentIndex: _currentIndex,
        // タップ時のハンドラ
        onTap: (selectedIndex) => setState(() {
          _currentIndex = selectedIndex;
        }),
        // ページ下部に表示するアイテム
        items: const [
          // labelは必須プロパティ
          BottomNavigationBarItem(icon: Icon(Icons.home), label: "home"),
          BottomNavigationBarItem(
              icon: Icon(Icons.calendar_month), label: "calendar"),
          BottomNavigationBarItem(icon: Icon(Icons.settings), label: "setting"),
        ],
      ),
    );
  }
}

よくあるトラブル

itemsが4つ以上定義されるとウィジェットが表示されない

原因はドキュメントによるとitemsが4つ以上だと、typeBottomNavigationBarType.shiftingに指定されるため。

The bottom navigation bar's type changes how its items are displayed. If not specified, then it's automatically set to BottomNavigationBarType.fixed when there are less than four items, and BottomNavigationBarType.shifting otherwise.

するとアイテムの色がScaffoldの背景色と同じになり、ぱっと見何も表示されていない様に見える。

そこで以下の方法で対応できる。

方法1: typeBottomNavigationBarType.fixedに指定する

typeを明示的に指定することでウィジェットが見える様になる。

class _TestPageState extends State<TestPage> {
  // ...

  
  Widget build(BuildContext context) {
    return Scaffold(
      // ...
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed, // 追記
        // ...
      ),
    );
  }
}

方法2: BottomNavigationBarItem.backgroundColorを指定する

背景と同化しているだけなので、色をつけると見える様になる。

class _TestPageState extends State<TestPage> {
  // ...
  
  Widget build(BuildContext context) {
    return Scaffold(
      // ...
      bottomNavigationBar: BottomNavigationBar(
        // ...
        items: const [
          // labelは必須プロパティ
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: "home",
            backgroundColor: Colors.grey, // 色を指定
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.calendar_month),
            label: "calendar",
            backgroundColor: Colors.grey, // 色を指定
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            label: "setting",
            backgroundColor: Colors.grey, // 色を指定
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: "account",
            backgroundColor: Colors.grey, // 色を指定
          ),
        ],
      ),
    );
  }
}

ただしこの方法だとBottomNavigationBarType.shiftingでレンダリングされる。
BottomNavigationBarType.fixedとは挙動が少し異なるので、実現したい動作に応じて使い分ける必要がある。

エラー Every item must have a non-null label'package:flutter/src/material/bottom_navigation_bar.dart'

labelが指定されていないBottomNavigationBarItemがあるためエラーが表示される。
labelに何かしらの文字列を渡すことで解決する。

リンク

公式ドキュメント
https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html

Navigation barドキュメント
https://m3.material.io/components/navigation-bar/overview

Discussion