aptik
aptik

Reputation: 613

Multi tab / page view in flutter

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.

Upvotes: 9

Views: 12593

Answers (1)

Collin Jackson
Collin Jackson

Reputation: 116708

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'),
          ),
        ],
      ),
    );
  }
}

Upvotes: 21

Related Questions