cover image
Nitish Kumar Singh
Nitish Kumar Singh
Clock Image 8 minutes
Posted on
December 7, 2020

Flutter : Save page state when using bottom Nav


In this article, I will solve one of the common problems. The problem is when they switch between two pages using bottom navigation it doesn’t keep the state of the page.

I am going to solve this problem using IndexedStack and if you know about this then probably you `already knew this. There are some chances you don’t know how to use IndexedStack then you should read and get the idea.

Get Started #

First of all, we will create a simple application that will have two pages and we will use bottom navigation for switching pages.

project-structure
├── android
├── ios
├── lib
│   ├── main.dart
│   ├── home.dart
│   └── screens
│       ├── page1.dart
│       └── page2.dart
└── pubspec.yaml

Step 1 #

Let’s create/edit our first file main.dart. This page will have very little code and it doesn’t require any explanation.

main.dart
import 'package:demo_app/home.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

Step 2 #

Let’s create the second file home.dart and this is going to have bottom nav logic.

home.dart
import 'package:demo_app/screens/page1.dart';
import 'package:demo_app/screens/page2.dart';
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final List<Widget> pages = [Page1(), Page2()];
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Save Page State'),
      ),
      body: pages[selectedIndex],
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.exposure_minus_1_outlined),
            label: 'Increment',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.plus_one_outlined),
            label: 'Decrement',
          ),
        ],
        currentIndex: selectedIndex,
        onTap: (index){
            setState(() {
                selectedIndex = index;
            });
        },
      ),
    );
  }
}
  • We will have 2 page
    • page1 : This screen have a increment the counter.
    • page2 : This screen have a decrement the counter.
  • At once there will be one tab selected, so there will a variable which will hold the active tab index.

Step 3 #

Let’s create page1.dart, this page will be created inside the screens directory. you can refer to the project structure above.

  • This page will have a increment counter.
page1.dart
import 'package:flutter/material.dart';

class Page1 extends StatefulWidget {
  @override
  _Page1State createState() => _Page1State();
}

class _Page1State extends State<Page1> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
        Center(
          child: Text(
            '$count',
            style: Theme.of(context).textTheme.headline2,
          ),
        ),
        RaisedButton(
          onPressed: () {
            setState(() {
              count++;
            });
          },
          child: Text('Increment'),
        )
      ],
    );
  }
}

Step 4 #

Let’s create page2.dart, this page will be created inside the screens directory.

  • This page will have a decrement counter.
page2.dart
import 'package:flutter/material.dart';

class Page2 extends StatefulWidget {
  @override
  _Page2State createState() => _Page2State();
}

class _Page2State extends State<Page2> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
        Center(
          child: Text(
            '$count',
            style: Theme.of(context).textTheme.headline2,
          ),
        ),
        RaisedButton(
          onPressed: () {
            setState(() {
              count--;
            });
          },
          child: Text('Decrement'),
        )
      ],
    );
  }
}

Looking for Flutter Developer

Hire Now

Final #

Now we will persist the state of the page and for that, we will use IndexedStack. This is one of simplest solution which can help you persist the state.

home.dart
import 'package:demo_app/screens/page1.dart';
import 'package:demo_app/screens/page2.dart';
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final List<Widget> pages = [Page1(), Page2()];
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Save Page State'),
      ),
//    body: pages[selectedIndex]
      body: IndexedStack(
        index: selectedIndex,
        children: pages,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.exposure_minus_1_outlined),
            label: 'Increment',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.plus_one_outlined),
            label: 'Decrement',
          ),
        ],
        currentIndex: selectedIndex,
        onTap: (index){
            setState(() {
                selectedIndex = index;
            });
        },
      ),
    );
  }
}

After using this you can switch the screen and you will find that the state of the counter doesn’t loose. This was the thing which we were trying to achieve.

Conclusion #

I hope you got the idea and you learned something new today. If you liked this want to support me then please share your valuable feedback or share this article with your friends.

Last updated at Monday, Dec 28, 2020 by Nitish Kumar Singh
comments powered by Disqus

Subscribe to our Newsletter


Tweet this article