简体   繁体   中英

Flutter navigationBar with Riverpod

I try to manage my states but I can't really do it. I would like to learn how to create a navigation bar at the bottom of the manage page with the riverpod package.

I manage to manage the page on which we click but I do not see how to then return the correct pager according to the selected button

Main.dart :

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:app/ui/screens/my_app/my_app_screen.dart';

void main() {
  runApp(
    const ProviderScope(child: MyApp()),
  );
}

NavigationBarScreen.dart:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

final provider = StateNotifierProvider((ref) => NavigationNotifier());

class NavigationBarScreen extends HookWidget
{
  @override
  Widget build(BuildContext context) {

    return SafeArea(
      child: Scaffold(
        body : Container(
              margin: EdgeInsets.only(left : 8, right : 8, bottom: 8),
              decoration: BoxDecoration(
                borderRadius: BorderRadius.only(
                    topRight: Radius.circular(20), topLeft: Radius.circular(20)),
                boxShadow: [
                  BoxShadow(color: AppColors.colorShadowLight, spreadRadius: 0, blurRadius: 10),
                ],
              ),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(50.0),
                child: BottomNavigationBar(
                  type: BottomNavigationBarType.fixed,
                  backgroundColor: AppColors.colorBgDark,
                  fixedColor: AppColors.colorContrastOrange,
                  unselectedItemColor: AppColors.colorFontLight2,
                  currentIndex: 0,
                  showSelectedLabels: false,
                  showUnselectedLabels: false,
                  onTap: context.read(provider).selectPage,
                  items: [
                    BottomNavigationBarItem(
                      icon: Icon(Icons.home),
                      title: Text('Home'),
                    ),
                    BottomNavigationBarItem(
                      icon: Icon(Icons.settings),
                      title: Text('Settings'),
                    ),
                  ],
                ),
              ),
            ),
      ),
    );
  }
}

NavigationNotifier.dart:

import 'package:hooks_riverpod/hooks_riverpod.dart';

enum NavigationBarEvent { HOME, PROFIL}

class NavigationNotifier extends StateNotifier<PageModel> {
  NavigationNotifier() : super(defaultPage);

  static const defaultPage = PageModel(NavigationBarEvent.HOME);

  void selectPage(int i){
    switch (i) {
      case 0:
        state = PageModel(NavigationBarEvent.HOME);
        break;
      case 1:
        state = PageModel(NavigationBarEvent.PROFIL);
        break;
    }
  }
}

class PageModel {
  const PageModel(this.page);
  final NavigationBarEvent page;
}

It appears that you have implemented all the logic for modifying the state when the user clicks on the bottom bar.

The only remaining bit is to listen to the state (likely in your Scaffold), and decide which page to show.

A possibility is to write:

class NavigationBarScreen extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final pageModel = useProvider(provider.state);

    Widget body;
    switch (pageModel.page) {
      case NavigationBarEvent.HOME:
        body = Home();
        break;
      case NavigationBarEvent.PROFIL:
        body: Profile();
        break;
    }

    return Scaffold(
      body: body,
      bottomBar: ...
    );
  }
} 

Updated Jan 27, 2022. https://pub.dev/packages/flutter_riverpod/versions/1.0.3

This is another approach that worked for me, if you are looking to control "pageview + bottom navigation bar" on drag as well:

class Index extends StateNotifier<int> {
  Index() : super(0);
  set value(int index) => state = index;
}

final indexProvider = StateNotifierProvider((ref) => Index());

class Home extends ConsumerWidget {
  static const route = '/home';
  const Home({Key? key}) : super(key: key);

  final List<Widget> fragments = const [
    Text('Page 1'),
    Text('Page 2'),
    Text('Page 3')
  ];

  final List<BottomNavigationBarItem> navItems = const [
    BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
    BottomNavigationBarItem(icon: Icon(Icons.camera), label: 'Camera'),
    BottomNavigationBarItem(icon: Icon(Icons.edit), label: 'Edit'),
  ];

  final Text title = const Text('My App');

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final PageController controller = PageController();
    final int menuIndex = ref.watch(indexProvider) as int;
    return Scaffold(
      appBar: AppBar(title: title, actions: [
        IconButton(onPressed: () {}, icon: const Icon(Icons.list))
      ]),
      body: PageView(
          controller: controller,
          children: fragments,
          onPageChanged: (i) => ref.read(indexProvider.notifier).value = i),
      bottomNavigationBar: BottomNavigationBar(
          items: navItems,
          currentIndex: menuIndex,
          onTap: (i) {
            ref.read(indexProvider.notifier).value = i;
            controller.animateToPage(i,
                duration: const Duration(seconds: 1), curve: Curves.easeInOut);
          }),
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM