Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve widget states in flutter, when navigating using BottomNavigationBar?

Tags:

flutter

dart

I'm currently working on building a Flutter app that will preserve states when navigating from one screen, to another, and back again when utilizing BottomNavigationBar. Just like it works in the Spotify mobile application; if you have navigated down to a certain level in the navigation hierarchy on one of the main screens, changing screen via the bottom navigation bar, and later changing back to the old screen, will preserve where the user were in that hierarchy, including preservation of the state.

I have run my head against the wall, trying various different things without success.

I want to know how I can prevent the pages in pageChooser(), when toggled once the user taps the BottomNavigationBar item, from rebuilding themselves, and instead preserve the state they already found themselves in (the pages are all stateful Widgets).

import 'package:flutter/material.dart'; import './page_plan.dart'; import './page_profile.dart'; import './page_startup_namer.dart';  void main() => runApp(new Recipher());  class Recipher extends StatelessWidget {   @override   Widget build(BuildContext context) {     return new Pages();   } }  class Pages extends StatefulWidget {   @override   createState() => new PagesState(); }  class PagesState extends State<Pages> {   int pageIndex = 0;     pageChooser() {     switch (this.pageIndex) {       case 0:         return new ProfilePage();         break;        case 1:         return new PlanPage();         break;        case 2:         return new StartUpNamerPage();          break;          default:         return new Container(           child: new Center(             child: new Text(               'No page found by page chooser.',               style: new TextStyle(fontSize: 30.0)               )             ),           );          }   }    @override   Widget build(BuildContext context) {     return new MaterialApp(       home: new Scaffold(         body: pageChooser(),         bottomNavigationBar: new BottomNavigationBar(           currentIndex: pageIndex,           onTap: (int tappedIndex) { //Toggle pageChooser and rebuild state with the index that was tapped in bottom navbar             setState(               (){ this.pageIndex = tappedIndex; }               );              },           items: <BottomNavigationBarItem>[             new BottomNavigationBarItem(               title: new Text('Profile'),               icon: new Icon(Icons.account_box)               ),               new BottomNavigationBarItem(                 title: new Text('Plan'),                 icon: new Icon(Icons.calendar_today)               ),                 new BottomNavigationBarItem(                 title: new Text('Startup'),                 icon: new Icon(Icons.alarm_on)               )             ],           )       )     );   } } 
like image 626
ArtBelch Avatar asked Mar 22 '18 21:03

ArtBelch


People also ask

How do you preserve the state in flutter?

We use Keys to preserve the user scroll location or keeping state when modifying a collection. If the entire widget subtree is stateless you don't need a key. Now let see when to use the keys. We know that we use keys to preserve states when widgets move around the widget subtree.

How do I use PageStorage in flutter?

By adding a PageStorage at the root and adding a PageStorageKey to each page, some of the page's state (e.g. the scroll position of a Scrollable widget) will be stored automatically in its closest ancestor PageStorage, and restored when it's switched back.

What is Indexstack in flutter?

An IndexedStack is a stack where only one component is shown at one time by its index. A Stack that shows a solitary child from a list of children. The showed child is the one with the given index. The stack is consistently just about as large as the biggest child.


2 Answers

For keeping state in BottomNavigationBar, you can use IndexedStack

    @override       Widget build(BuildContext context) {         return Scaffold(           bottomNavigationBar: BottomNavigationBar(             onTap: (index) {               setState(() {                 current_tab = index;               });             },             currentIndex: current_tab,             items: [               BottomNavigationBarItem(                 ...               ),               BottomNavigationBarItem(                 ...               ),             ],           ),           body: IndexedStack(             children: <Widget>[               PageOne(),               PageTwo(),             ],             index: current_tab,           ),         );       } 
like image 180
Newaj Avatar answered Sep 27 '22 15:09

Newaj


Late to the party, but I've got a simple solution. Use the PageView widget with the AutomaticKeepAliveClinetMixin.

The beauty of it that it doesn't load any tab until you click on it.


The page that includes the BottomNavigationBar:

var _selectedPageIndex; List<Widget> _pages; PageController _pageController;  @override void initState() {   super.initState();    _selectedPageIndex = 0;   _pages = [     //The individual tabs.   ];    _pageController = PageController(initialPage: _selectedPageIndex); }  @override void dispose() {   _pageController.dispose();    super.dispose(); }  @override Widget build(BuildContext context) {   ...     body: PageView(       controller: _pageController,       physics: NeverScrollableScrollPhysics(),       children: _pages,     ),    bottomNavigationBar: BottomNavigationBar(       ...       currentIndex: _selectedPageIndex,       onTap: (selectedPageIndex) {         setState(() {           _selectedPageIndex = selectedPageIndex;           _pageController.jumpToPage(selectedPageIndex);         });       },   ... } 

The individual tab:

class _HomeState extends State<Home> with AutomaticKeepAliveClientMixin<Home> {   @override   bool get wantKeepAlive => true;    @override   Widget build(BuildContext context) {     //Notice the super-call here.     super.build(context);     ...   } } 

I've made a video about it here.

like image 42
Tayan Avatar answered Sep 27 '22 17:09

Tayan