🐈

flutter✖️goRouter✖️bottomNavigationBar

2024/05/02に公開

どうも!初心者flutterプログラマーのちゃきです!
今回は、goRouterでBottomNavigationBarを作成してみた記録をします✏️
BottomNavigationBarのShellRouteに関しては、この動画がとてもわかりやすかったので
とってもおすすめです☺️

https://www.youtube.com/watch?v=kfvHk5Q88fQ

GoRouterProviderの作成を

import 'package:firebase_app/config/enum/router_enum.dart';
import 'package:firebase_app/features/auth/view/auth_page.dart';
import 'package:firebase_app/features/cloud_store/view/cloud_store_page.dart';
import 'package:firebase_app/features/storage/view/storage_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';

import '../navigation/bottom_navigation_bar_page.dart';

final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _shellNavigationKey = GlobalKey<NavigatorState>();

final goRouterProvider = Provider<GoRouter>(
  (ref) {
    return GoRouter(
      initialLocation: AppRoute.auth.path,
      navigatorKey: _rootNavigatorKey,
      routes: <RouteBase>[
        //[ShellRoute] = 画面全体とは別に遷移管理させる。
        ShellRoute(
          navigatorKey: _shellNavigationKey, //RouteBaseと別に独立してページの管理ができる。

          builder: (context, state, child) { //bottomnavigationbarを残せる
            // (文脈、状態、child)
            return BottomNavigationBarPage(child: child);
          },
          //ShellRouteの中にいる画面は、画面全体とは別の遷移管理対象になる。
          routes: [
            GoRoute(
              path: AppRoute.auth.path, // トップレベルのパスが必要なので指定する.
              name: AppRoute.auth.name,
              builder: (BuildContext context, GoRouterState state) {
                return const AuthPage();
              },
            ),
            GoRoute(
              path: AppRoute.cloudStore.path,
              name: AppRoute.cloudStore.name,
              builder: (BuildContext context, GoRouterState state) {
                return const CloudStorePage();
              },
            ),
            GoRoute(
              path: AppRoute.storage.path,
              name: AppRoute.storage.name,
              builder: (BuildContext context, GoRouterState state) {
                return const StoragePage();
              },
            ),
          ],
        ),
      ],
    );
  },
);

main.dartでgoRouterProviderを使えるように設定する

import 'package:firebase_app/routing/app_router.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  //MyAppをProviderScopeに指定し、全てのページでProviderを使えるようにする
  runApp(
    const ProviderScope(child: MyApp()),
  );
}

class MyApp extends ConsumerWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // go_routerプロバイダーを監視する。
    final goRouter = ref.watch(goRouterProvider);
    return MaterialApp.router(
      debugShowCheckedModeBanner: false,
      // MaterialAppにrouterを追加。
      routerConfig: goRouter, //goRouterを基盤に設定する。
      title: 'riverpod ✖️ go_router',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
    );
  }
}

BottomNavigationBarPage

・ 「currentIndex: _selectedIndex.value」 で、activeなindexを設定する。
・ onTap(){}の処理で、まず選ばれているindexを変えて、その次にvalueに合わせてページ遷移させる。

import 'package:firebase_app/features/auth/view/auth_page.dart';
import 'package:firebase_app/features/cloud_store/view/cloud_store_page.dart';
import 'package:firebase_app/features/storage/view/storage_page.dart';
import 'package:firebase_app/routing/app_router.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

import '../config/enum/router_enum.dart';

class BottomNavigationBarPage extends HookConsumerWidget {
  const BottomNavigationBarPage({super.key, required this.child});
  final Widget child;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final _selectedIndex = useState(0); //初期値

    return Scaffold(
      appBar: AppBar(),
      body: child,
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex.value, //今現在選択されているindexを設定する。
        onTap: (value) {
          //bottomnavigationbaritemがタップされるたびに、中の処理が走る。
          //itemがタップされるたびに_selecredIndex.valueが書き換えられる。
          _selectedIndex.value = value;
          print(value);
          switch (value) {
            case 0:
              context.goNamed(AppRoute.auth.name);
              break;
            case 1:
              context.goNamed(AppRoute.cloudStore.name);
              break;
            case 2:
              context.goNamed(AppRoute.storage.name);
              break;
          }
        },
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.person), label: 'auth'),
          BottomNavigationBarItem(icon: Icon(Icons.book), label: 'cloudstore'),
          BottomNavigationBarItem(icon: Icon(Icons.storage), label: 'storage'),
        ],
      ),
    );
  }
}

おわりに

ここまで読んでくださりありがとうございました✨
今のコードのままでは、ページをリフレッシュした際にauthPageに戻ってしまう問題があるので、この問題を解消してまた記事を書きたいと思います!🫡

Discussion