Search code examples
flutterflutter-layoutflutter-pageview

Using DefaultTabController in widget tree with variable height


In my app I have a PageView and then in that PageView I have some tabbed content (through use of DefaultTabController). In those tabs, I have some content of variable height. No matter what I do, whenever I try to use the DefaultTabController, Flutter throws this error:

Viewports expand in the cross axis to fill their container and constrain their children to match their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of vertical space in which to expand.
The relevant error-causing widget was: 
  TabBarView file:///C:/code/samples/tabbed/lib/main.dart:104:23

I have tried:

  • Wrapping everything in a ListView with shrinkWrap: true
  • Using a Column with a minimum Main Axis Size

No matter what I do the TabBarView always tries to render off into infinity. How can I use a DefaultTabController to show variable height tabs?

This is my code:

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: PageView(
        children: [
          Container(
            height: 200,
            color: Colors.blueGrey,
            child: DefaultTabController(
              length: 2,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  TabBar(
                    tabs: [
                      Tab(
                        text: "Okay",
                      ),
                      Tab(
                        text: "Go",
                      )
                    ],
                  ),
                  ListView(
                    scrollDirection: Axis.vertical,
                    shrinkWrap: true,
                    children: [
                      TabBarView(
                        children: [
                          Text("one"),
                          Text("two"),
                        ],
                      )
                    ],
                  ),
                ],
              ),
            ),
          ),
          Container(
            color: Colors.deepOrange,
          ),
          Container(
            color: Colors.cyan,
          )
        ],
      ),
    );
  }

Solution

  • Remove the ListView and wrap TabBarView with Expanded, and you should be good to go:

    Expanded(
      child: TabBarView(
        children: [
          Text("one"),
          Text("two"),
        ],
      ),
    )
    

    Note that now you have a conflict between TabBarView and PageView swiping gestures (You can only swipe the PageView from the TabBar since everything below the latter is covered by TabBarView)