Search code examples
flutterlistviewdartflutter-layouttabview

Preserving state between tab view pages


issue

I have two ListViews rendering inside of a TabBarView using a TabController.

How do I preserve state (for lack of a better word) between each ListView so that: 1.) the Widgets don't rebuild and 2.) the ListView position is remembered between tabs.

relevant code

class AppState extends State<App> with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = new TabController(
      vsync: this,
      length: _allPages.length,
    );
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  Widget _buildScaffold(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('headlines'),
        bottom: new TabBar(
            controller: _tabController,
            isScrollable: true,
            tabs: _allPages
                .map((_Page page) => new Tab(text: page.country))
                .toList()),
      ),
      body: new TabBarView(
          controller: _tabController,
          children: _allPages.map((_Page page) {
            return new SafeArea(
              top: false,
              bottom: false,
              child: new Container(
                key: new ObjectKey(page.country),
                child: new Newsfeed(country: page.country),
              ),
            );
          }).toList()),
    );
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'news app',
      home: _buildScaffold(context),
    );
  }
}

illustrating gif

https://media.giphy.com/media/2ysWhzqHVqL1xcBlBE/giphy.gif


Solution

  • In case you want to keep the state of your screen in your TabBarView, you can use the mixin class called AutomaticKeepAliveClientMixin in your State class.

    After that you have to override the wantKeepAlive method and return true. It will looks like something that :

    class _SearchScreenState extends State<SearchScreen> with AutomaticKeepAliveClientMixin<SearchScreen>{
    
    ...
    
      @override
      Widget build(BuildContext context) { 
        // call this method
        super.build(context); 
    
        /// your widget here
      }
    
      @override
      bool get wantKeepAlive => true;
    
    }
    

    I wrote a post about that here: https://medium.com/@diegoveloper/flutter-persistent-tab-bars-a26220d322bc