Force TabController to create all tabs Flutter

Viewed 935

I have a default page with two tabs, using TabBar and TabController. All is working fine, except when I enter the page, the second tab's build method is only called when I click to change to the second tab. The problem is that when I enter the page I want both tabs to be already created (a.k.a their build methods executed). Any thoughts?

Illustration code:

//This widget is used inside a Scaffold
class TabsPage extends StatefulWidget {

  @override
  State<StatefulWidget> createState() => new TabsPageState();

}

class TabsPageState extends State<TabsPage> with TickerProviderStateMixin {

  List<Tab> _tabs;
  List<Widget> _pages;
  TabController _controller;

  @override
  void initState() {
    super.initState();
    _tabs = [
      new Tab(text: 'TabOne'),
      new Tab(text: 'TabTwo')
    ];
    _pages = [
      //Just normal stateful widgets
      new TabOne(),
      new TabTwo()
    ];
    _controller = new TabController(length: _tabs.length, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return new Padding(
      padding: EdgeInsets.all(10.0),
      child: new Column(
        children: <Widget>[
          new TabBar(
            controller: _controller,
            tabs: _tabs
          ),
          new SizedBox.fromSize(
            size: const Size.fromHeight(540.0),
            child: new TabBarView(
                controller: _controller,
                children: _pages
            ),
          )
        ],
      ),
    );
  }

}
2 Answers

I had a similar issue, I'm using Tabs with Forms and I wanted to validate all of them, my solution was to switch to the second tab programmatically, It doesn't make sense to not visit a tab with a form that requires validation.

So given a global key for each form:

final _formKey = GlobalKey<FormState>();

The reason I wanted all tabs to be built was to use:

_formKey.currentState.validate()

So my fix is

if (_formKey.currentState == null) { //The tab was never visited, force it
  _tabController.animateTo(1);
  return;
}

I was able to achieve this.

In my case, I had 2 tabs and I wanted to preload the other tab.

So what I did was, I initialised the tab controller in initState like this:

tabController = TabController(
  length: 2,
  vsync: this,
  initialIndex: 1,
);

I set the initialIndex to the other tabs index, and then set the index back in after the build was done like this:

WidgetsBinding.instance.addPostFrameCallback((_) {
  tabController.index = 0;
});

But this may only work if you have 2 tabs

Related