🌴
[Flutter×Riverpod]BottomNavigationBarを勉強してみた
はじめに
下記のUrasanさんによる「BottomNavigationBarを本気で学ぶ」を参考にBottomNavigationBarの勉強をしてました。
本業で扱っているアプリがRiverpodを使用してのアプリ開発を行なっていて、全くRiverpod×、BottomNavigationBarの理解できていなかったため、夏休み中に勉強しよう!と考えました。
今回、Urasanさんの記事を軸にRiverpodを使用した、BottomNavigationBarのざっくり記事になります。
ディレクトリ、ファイル構成
lib --
| riverpod ------------------------
| |
- bottomnavigationbar.dart - app_bottom_navigation_bar.dart
- main.dart - screen_index_provider.dart
- page1.dart - tab_Index_provider.dart
- page2.dart
- page3.dart
- page4.dart
メインとなるファイルはBottomNavigationBarPage、AppBottomNavigationBar
の二つとなります。
BottomNavigationBarPage
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:prefectures47/page1.dart';
import 'package:prefectures47/page2.dart';
import 'package:prefectures47/page3.dart';
import 'package:prefectures47/page4.dart';
import 'package:prefectures47/riverpod/app_bottom_navigation_bar.dart';
import 'package:prefectures47/riverpod/screen_index_provider.dart';
import 'package:prefectures47/riverpod/tab_Index_provider.dart';
class BottomNavigationBarPage extends ConsumerStatefulWidget {
const BottomNavigationBarPage({Key? key}) : super(key: key);
_BottomNavigationBarPageState createState() =>
_BottomNavigationBarPageState();
}
class _BottomNavigationBarPageState
extends ConsumerState<BottomNavigationBarPage> {
static final List<Widget> _pageList = [
//1ページ
const PageWidget1(),
//2ページ
const PageWidget2(),
//3ページ
const PageWidget3(),
//4ページ
const PageWidget4(),
];
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Riverpod Test'),
),
body: _pageList.elementAt(ref.watch(screenIndexProvaider)),
bottomNavigationBar: AppBottomNavigationBar(
curretPage: ref.watch(tabIndexProvider),
tap: (tab) => _onTap(tab, context),
),
);
}
void _onTap(int tab, BuildContext context) {
switch (tab) {
case 0:
ref.read(tabIndexProvider.state).state = tab;
break;
case 1:
ref.read(tabIndexProvider.state).state = tab;
break;
case 2:
ref.read(tabIndexProvider.state).state = tab;
break;
case 3:
ref.read(tabIndexProvider.state).state = tab;
break;
}
}
}
ConsumerStatefulWidget とは
公式から一部引用。
ref オブジェクトが使用できるようにするため
StatefulWidget+State の代わりに ConsumerStatefulWidget+ConsumerState を継承する。
class BottomNavigationBarPage extends ConsumerStatefulWidget {
ref.watch を使ってプロバイダを監視する
ref.watch: プロバイダの値を取得した上で、その変化を監視する。値が変化すると、その値に依存するウィジェットやプロバイダの更新が行われる。
※上記の内容は公式から引用
screenIndexProvaiderを監視する。
body: _pageList.elementAt(ref.watch(screenIndexProvaider.state).state),
curretPage: ref.watch(tabIndexProvider),
tap: (tab) => _onTap(tab, context),
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:prefectures47/riverpod/tab_Index_provider.dart';
// 画面が切り替わった場合でも、どのスクリーンを表示させているのかを保持するプロバイダー
final screenIndexProvaider = StateProvider<int>((ref) {
// タブの状態を読みとる
final tabIndex = ref.watch(tabIndexProvider.state).state;
return tabIndex;
});
import 'package:flutter_riverpod/flutter_riverpod.dart';
// どのタブを表示しているのか状態を保持するプロバイダー
final tabIndexProvider = StateProvider<int>((ref) => 0);
AppBottomNavigationBar
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class AppBottomNavigationBar extends StatefulWidget {
const AppBottomNavigationBar(
{required this.curretIndex, required this.onTap});
final int curretIndex;
final ValueChanged<int> onTap;
_AppBottomNavigationBarState createState() => _AppBottomNavigationBarState();
}
class _AppBottomNavigationBarState extends State<AppBottomNavigationBar> {
Widget build(BuildContext context) {
return Consumer(builder: (context, ref, child) {
return BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: _bottomNavigationBarIcon(index: 0), label: 'ページ1'),
BottomNavigationBarItem(
icon: _bottomNavigationBarIcon(index: 1), label: 'ページ2'),
BottomNavigationBarItem(
icon: _bottomNavigationBarIcon(index: 2), label: 'ページ3'),
BottomNavigationBarItem(
icon: _bottomNavigationBarIcon(index: 3), label: 'ページ4'),
],
currentIndex: widget.curretIndex,
onTap: widget.onTap,
type: BottomNavigationBarType.fixed,
);
});
}
}
Widget _bottomNavigationBarIcon({required index}) {
return Container();
}
プロパティ
プロパティ | 説明 |
---|---|
currentIndex | 現在アクティブなBottomNavigationBarItemの項目へのインデックス |
onTap | ページ1つがタップされたときに呼び出し |
type | BottomNavigationBarのレイアウトと動作を定義 |
終わりに
エンジニア初学者なので、まだまだ詳しく説明できていない部分がありますが、
旧Providerだとツリー構造なので、近くの値からしか取得できませんがRiverpodはグローバルに値を取得できるのでとても便利ですね!
これからFlutterエンジニア目指すかたは、Riverpodでアプリを作ると好印象間違いないでしょう!
下記コミュニティは、私がエンジニア未経験から転職まで導いていただいたコミュニティ。
興味があれば是非!!
Discussion