DartでTabbarを使用する
公開日: 2024-12-26 11:24:06
今日はDartでTabBarを作成するコードを記載していきます。
TabBarとは画面の下部のボタンアイコンのことで、一番最初に設定しておかないと値の受け渡しや階層が複数ある画面を表示した際の挙動等で結構大変なことになります。
逆に最初に設定すると全体のコードをどのように書いていくばいいのかが、見渡せるようになります。
構造(MVVM)
lib/
├── main.dart
├── views/
│ ├── main_view.dart
│ ├── screen_one.dart
│ ├── screen_two.dart
│ ├── screen_three.dart
│ ├── screen_four.dart
├── viewmodels/
│ └── main_viewmodel.dart
main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'viewmodels/main_viewmodel.dart';
import 'views/main_view.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => MainViewModel(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BottomNavigationBar with MVVM',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MainView(),
);
}
}
viewmodels/main_viewmodel.dart
import 'package:flutter/material.dart';
import '../views/screen_one.dart';
import '../views/screen_two.dart';
import '../views/screen_three.dart';
import '../views/screen_four.dart';
class MainViewModel extends ChangeNotifier {
int _selectedIndex = 0;
// 画面リスト
final List<Widget> _screens = [
ScreenOne(),
ScreenTwo(),
ScreenThree(),
ScreenFour(),
];
// 現在選択されているインデックス
int get selectedIndex => _selectedIndex;
// 現在の画面リスト
List<Widget> get screens => _screens;
// インデックス変更
void changeScreen(int index) {
_selectedIndex = index;
notifyListeners(); // Viewに変更を通知
}
}
views/main_view.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../viewmodels/main_viewmodel.dart';
class MainView extends StatelessWidget {
@override
Widget build(BuildContext context) {
final viewModel = context.watch<MainViewModel>();
return Scaffold(
appBar: AppBar(
title: Text('MVVM Navigation Example'),
),
body: viewModel.screens[viewModel.selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.notifications),
label: 'Notifications',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Settings',
),
],
currentIndex: viewModel.selectedIndex,
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
onTap: (index) => viewModel.changeScreen(index),
),
);
}
}
views/screen_one.dart
import 'package:flutter/material.dart';
class ScreenOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'Home Screen',
style: TextStyle(fontSize: 24),
),
);
}
}
views/screen_two.dart
import 'package:flutter/material.dart';
class ScreenTwo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'Search Screen',
style: TextStyle(fontSize: 24),
),
);
}
}
views/screen_three.dart
import 'package:flutter/material.dart';
class ScreenThree extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'Notifications Screen',
style: TextStyle(fontSize: 24),
),
);
}
}views/screen_four.dart
import 'package:flutter/material.dart';
class ScreenFour extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'Settings Screen',
style: TextStyle(fontSize: 24),
),
);
}
}
実行結果

ポイント
・main.dart: アプリ全体のエントリーポイントとして、MainViewModel を Provider 経由でアプリに注入します。
・ViewModel: viewmodels/ ディレクトリに MainViewModel を定義し、状態管理ロジックを記述します。
・View: 各画面(ScreenOne など)を views/ ディレクトリに分けて、独立したUIロジックを記述します。
・こちらの書き方をしていたら、新しい画面を追加する際は、views/ に新しい画面を追加し、MainViewModel の _screens リストにその画面を加えるだけで済みます。