Search code examples
routesflutterkeybottomnavigationviewnavigator

BottomNavigationBar saving offset position and navigating to details flutter


I'm new in flutter. I'm using Scoped Model in project (and auto authentication), and I use routes on MaterialApp class

@override
    void initState() {

      _model.autoAuthenticate();
      _model.userSubject.listen((bool isAuthenticated){
        setState(() {
          _isAuthenticated = isAuthenticated;
        });
      });
      print('is auth $_isAuthenticated');
      super.initState();
    }

    @override
    Widget build(BuildContext context) {
      return ScopedModel<MainModel>(
        model: _model,
        child: MaterialApp(
          debugShowCheckedModeBanner: false,
          theme: getAdaptiveThemeData(context),
          routes: {
            '/': (BuildContext context) => !_isAuthenticated ? WelcomePage() : MainPage(_model),
            '/info': (BuildContext context) => InfoPage(),
            // another code

And in my '/' route I use MainPage() with 4 bottomNavigationBarItems and 4 different pages with code:

    int _currentTab = 0;
  final List<Widget> _children = [
    ScopedModelDescendant<MainModel>(
        builder: (BuildContext context, Widget child, MainModel model){
          return ProfilePage(model);
        },
    ),
    OnStockPage(),
    SendPage(),
    PppPage()
  ];

and in build widget:

@override
  Widget build(BuildContext context) {

    if(widget.model.isUserChanged){
      widget.model.getUserProfile().then((model){

      }).catchError((error){
        print('error is $error');
      });
    }

    print('build first');
    return StreamBuilder<UserModel>(
          stream: _bloc.user,
          builder: (BuildContext context, AsyncSnapshot<UserModel> snapshot){

              return Scaffold(
                appBar: AppBar(
                  title: ScopedModelDescendant<MainModel>(
                    builder: (BuildContext context, Widget child, MainModel model){
                      return ListTile(
                        title: model.isLoading ? Text('name surname', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)) : Text('${model.profile.firstName} ${model.profile.lastName}', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),),
                        subtitle: Text('Баланс \$0', style: TextStyle(color: Colors.white),),
                      );
                    },
                  ),
                  elevation: 0,
                ),
                drawer: DrawerSettings(),
                body:_children[_currentTab],

                bottomNavigationBar: BottomNavigationBar(
                  currentIndex: _currentTab,
                  items: [
                    BottomNavigationBarItem(
                        icon: Icon(Icons.person, color: Colors.black,),
                        title: Text('Профиль', style: TextStyle(color: Colors.black),)
                    ),
                    BottomNavigationBarItem(
                        icon: Icon(Icons.check_box_outline_blank, color: Colors.black),
                        title: Text('На складе', style: TextStyle(color: Colors.black),)
                    ),
                    BottomNavigationBarItem(
                        icon: Icon(Icons.drive_eta, color: Colors.black),
                        title: Text('Отправленные', style: TextStyle(color: Colors.black),)
                    ),
                    BottomNavigationBarItem(
                        icon: Icon(Icons.shopping_cart, color: Colors.black),
                        title: Text('ПпП', style: TextStyle(color: Colors.black))
                    ),
                  ],
                  onTap: _onTabTapped,
                ),
              );
           },
    );
  }

but when I am in the first bottom item I load all the data and everything is fine, but when I go to the second bottom item and back all the data is loaded again, without saving, etc. I found some code with Navigator class and Offstage class with bottomNavigationBar but they didn't use MaterialApp -> routes, but I use and because of this there are conflicts.. here is the link: https://medium.com/coding-with-flutter/flutter-case-study-multiple-navigators-with-bottomnavigationbar-90eb6caa6dbf And I want the app to already know these pages and not to call it constantly. Please help me


Solution

  • I found the solution of my question.. in body of Scaffold class ->

    body:_body(),
    

    and

    Widget _body(){
    
        return Stack(
          children: List<Widget>.generate(_pageCount, (int index){
            return IgnorePointer(
              ignoring: index != _currentTab,
              child: Opacity(
                opacity: _currentTab == index ? 1 : 0,
                child: Navigator(
                  onGenerateRoute: (RouteSettings settings){
                    print('settings ${settings.name}');
                    if(settings.name == '/'){
                      return MaterialPageRoute(
                          builder: (_) => _page(index),
                          settings: settings
                      );
                    }
                  },
                ),
              ),
            );
          })
        );
      }
    
      Widget _page(int index){
    
        switch (index){
          case 0:
            return ScopedModelDescendant<MainModel>(
              builder: (BuildContext context, Widget child, MainModel model){
                return /*(model.isLoading) ? Center(
                child: CircularProgressIndicator(),
              ) : */ProfilePage(model);
              },
            );
          case 1:
            return OnStockPage();
          case 2:
            return SendPage();
          case 3:
            return PppPage();
        }
        throw "Invalid index $index";
      }