9

How do i create a multi page view in flutter where the pages correspond to tabs in a bottomnavigationbar such that the widgets corresponding to the pages are built only once and on demand.

For eg., consider a simple facebook app kind of UI with two tabs - the feed and the notification with the following behavior:

  1. Both feed and notifications are list of items fetched over network.
  2. Assuming the original tab is feed, the notifications should be fetched only when user clicks on the notification tab
  3. If a user scrolls in the feed, and clicks on notification icon and then clicks again on feed icon, the scroll position should be remembered.

If i use a TabBarView, it rebuilds the widgets every time the tab is changed, so the scroll position is not retained.

1

1 Answer 1

21

To give the pages of the TabBarView a unique scroll position storage container, use a PageStorageKey.

video

import 'package:flutter/material.dart';

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

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

class MyHomePage extends StatefulWidget {
  @override
  State createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  TabController _controller;
  int _tab = 0;

  @override
  void initState() {
    _controller = new TabController(length: 2, vsync: this);
  }

  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text('Example App')),
      body: new TabBarView(
        controller: _controller,
        children: <Widget>[
          new ListView.builder(
            key: new PageStorageKey('feed'),
            itemBuilder: (BuildContext context, int index) {
              return new ListTile(
                title: new Text('Feed Item $index'),
              );
            },
          ),
          new ListView.builder(
            key: new PageStorageKey('notifications'),
            itemBuilder: (BuildContext context, int index) {
              return new ListTile(
                title: new Text('Notification $index'),
              );
            },
          ),
        ],
      ),
      bottomNavigationBar: new BottomNavigationBar(
        onTap: (int value) {
          _controller.animateTo(value);
          setState(() {
            _tab = value;
          });
        },
        currentIndex: _tab,
        items: <BottomNavigationBarItem>[
          new BottomNavigationBarItem(
            icon: new Icon(Icons.home),
            title: new Text('Home'),
          ),
          new BottomNavigationBarItem(
            icon: new Icon(Icons.notifications),
            title: new Text('Notifications'),
          ),
        ],
      ),
    );
  }
}
1
  • 1
    Whether this will work in Paginated List (List with infinity scroll) ?
    – Mithun S
    Commented May 17, 2020 at 11:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.