BottomNavigationBarとNavigationBarは、基本的にScaffoldのBottomに配置するナビゲーションバーという部品になる。
BottomNavigationBarはMaterial 2仕様でNavigationBarはMaterial 3仕様という違いがあるだけ。
上記のSee also:の中に「NavigationBar, this widget’s replacement in Material Design 3.」と書かれているし、Material 3のNavigation barのOverviewにも「There’s one type of navigation bar in Material. In M2, this component is named bottom navigation.」と記載されている。
ただBottomNavigationBarとNavigationBarはFlutterでは異なるクラスになるので、ThemeDataでuseMaterial3をtrueにしただけで切り替わるということではない。
そこでBottomNavigationBarにインターフェースが似た形でM2/M3の状態に合わせてBottomNavigationBar、NavigationBarを切り替えるウィジェットを作ってみた。
ソースコード
クラスのコードは以下の様な感じ。
色関係については割愛している。
/// [ThemeData]の[useMaterial3]の設定により[BottomNavigationBar]か[NavigationBar]
/// を切り替えて使用し、[Scaffold]の[bottomNavigationBar]に設定するナビゲーションバーを
/// 表示する
class AltBottomNavBar extends StatelessWidget {
const AltBottomNavBar(
{super.key, required this.items, this.onTap, this.currentIndex = 0});
/// Defines the appearance of the button items that are arrayed within the
/// bottom navigation bar.
final List<BottomNavigationBarItem> items;
/// Determines which one of the [items] is currently selected.
///
/// When this is updated, the destination (from [items]) at
/// [currentIndex] goes from unselected to selected.
final int currentIndex;
/// Called when one of the [items] is tapped.
final ValueChanged<int>? onTap;
@override
Widget build(BuildContext context) {
final useMaterial3 = Theme.of(context).useMaterial3;
return !useMaterial3
? BottomNavigationBar(
useLegacyColorScheme: false,
items: items,
currentIndex: currentIndex,
onTap: onTap,
)
: NavigationBar(
destinations: items
// BottomNavigationBarItemからNavigationDestinationに変換
.map<Widget>((e) => NavigationDestination(
label: e.label!,
selectedIcon: e.activeIcon,
icon: e.icon,
tooltip: tooltip: e.tooltip ?? "",
))
.toList(),
selectedIndex: currentIndex,
onDestinationSelected: onTap,
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
);
}
}
BottomNavigationBarItemからの変換
一番大きな変更点は、受け入れる表示アイテムがBottomNavigationBarItemからWidgetに変わった点。
NavigationBarはWidgetだけど実際に使用されるウィジェットはNavigationDestinationになるので、それへの変換を行う。
とは言っても、BottomNavigationBarItem自体はlabel, activeIcon, icon, tooltipを入れるコンテナとしての役割しか持っていないので、List.mapでNavigationDestinationに変換するだけで問題はない。
ツールチップの取り扱い
変換で注意が必要なのがツールチップ。
BottomNavigationBarではtooltipがnullの場合ツールチップの表示はされないのだけど、NavigationBarではtooltipがnullの場合labelと同じものが表示される。
上の動画は、前半がBottomNavigationBarで後半がNavigationBarになる。
BottomNavigationBarではツールチップが表示されいないけどNavigationBarでは表示されているのが見て取れると思う。
そういう意味で、NavigationDestinationのtooltipにはBottomNavigationBarItemのtooltipがnullの場合、空文字(“”)を設定するようにしている。
labelBehaviorの設定
BottomNavigationBarではデフォルトでは現在アクティブなもののもみlabelが表示されるが、NavigationBarはデフォルトすべての項目のlabelが表示される。
BottomNavigationBarの表示方法に合わせる場合「labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected」とすることで合わせることができる。
- BottomNavigationBar
- NavigationBar
コメント