56

I'm trying to make a profile page, where the users info is at the top. And then have a tab view below that for different views.

enter image description here

This is the code I'm using at the moment, when I take the TabBarView out it doesn't through an error, and if I wrap the TabBarView in an Expanded the error RenderFlex children have non-zero flex but incoming height constraints are unbounded. comes up.

     @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(''),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.all(10.0),
            child: Row(
              children: <Widget>[
                CircleAvatar(
                  minRadius: 45.0,
                  backgroundImage: NetworkImage(
                      'https://www.ienglishstatus.com/wp-content/uploads/2018/04/Anonymous-Whatsapp-profile-picture.jpg'),
                ),
                Padding(
                  padding: EdgeInsets.only(left: 10.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text(
                        'Testing Name',
                        style: TextStyle(
                          fontSize: 22.0,
                          color: Colors.grey.shade800,
                        ),
                      ),
                      Text(
                        '@testing_username',
                        style: TextStyle(
                          fontSize: 13.0,
                          color: Colors.grey.shade800,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),

          DefaultTabController(
            length: 3,
            child: Column(
              children: <Widget>[
                TabBar(
                  tabs: <Widget>[
                    Tab(
                      icon: Padding(
                        padding: EdgeInsets.all(6.0),
                        child: Image.asset(
                          "assets/images/icons/butterlike.png",
                          color: Colors.grey.shade800,
                        ),
                      ),
                    ),
                    Tab(
                      icon: Padding(
                        padding: EdgeInsets.all(6.0),
                        child: Image.asset(
                          "assets/images/icons/butterlike.png",
                          color: Colors.grey.shade800,
                        ),
                      ),
                    ),
                    Tab(
                      icon: Padding(
                        padding: EdgeInsets.all(6.0),
                        child: Image.asset(
                          "assets/images/icons/butterlike.png",
                          color: Colors.grey.shade800,
                        ),
                      ),
                    ),
                  ],
                ),

                TabBarView(
                  children: <Widget>[
                    Container(
                      color: Colors.grey,
                    ),
                    Container(
                      color: Colors.green,
                    ),
                    Container(
                      color: Colors.purple,
                    ),
                  ],
                ),
              ],
            ),
          )
        ],
      ),
    );
  }

I did try a variation of this but couldn't get it to work.

zimmerrol
  • 4,872
  • 3
  • 22
  • 41
TheFairywarrior
  • 718
  • 1
  • 8
  • 16

5 Answers5

66

The error description is clear, the TabBarView doesn't have a bounded height. the parent widget also doesn't have a bounded height. So, the Expanded widget will not solve this issue.

EDIT: below solutions are for above question(with columns).In general cases, use a ListView with shrinkWrap: true.(Or any other widgets with shrinkWrap) As @Konstantin Kozirev mentioned correctly, the shrinkWrap causes some performance issues. look for a better updated solution.

There are some options:

1st Solution:

Wrap the parent widget(Column) with a limited height widget like SizedBox or AspectRatio. Then use the Expanded widget like this:

Expanded(
  child: TabBarView(...),
)

2nd Solution:

Use a bounded widget like SizedBox or AspectRatio on the TabBarView itself:

SizedBox(
  height: 300.0,
  child: TabBarView(...),
)

Note Your can also calcuate the height dynamicly if the height is not static.

Yamin
  • 2,868
  • 1
  • 19
  • 22
15

I solved it by adding TabBar inside Container and TabBarView inside Expanded:

DefaultTabController(
    length: 3,
    child: Column(
      children: <Widget>[
        Container(child: TabBar(..)),
        Expanded(child: TabBarView(..)),
      ],
    ),
  );
temirbek
  • 1,415
  • 1
  • 14
  • 27
  • Use of Expanded widget is better in such BOUNDED HEIGHT issues. Especially when you don't want to define fixed height. Otherwise for dynamically calculating fixed height use - MediaQuery.of(context).size.height – abhay tripathi Apr 16 '20 at 10:15
  • I don't think the Container helps here, only wrapping TabBarView with Expanded should suffice – cksrc Oct 24 '22 at 18:34
12

try to use IndexedStack instead of TabBarView

i tried Expanded, shrinkWrap = true , ... but no one work's fine just try example.

Example:

class Product extends StatefulWidget {
  @override
  _ProductState createState() => _ProductState();
}

class _ProductState extends State<Product> with SingleTickerProviderStateMixin {
  TabController tabController;
  int selectedIndex = 0;

  @override
  void initState() {
    super.initState();
    tabController = TabController(length: 5, vsync: this, initialIndex: 0);
  }

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

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      initialIndex: 0,
      child: Scaffold(
        body: ListView(
          shrinkWrap: true,
          children: [
            TabBar(
         
              tabs: <Widget>[
                Tab(
                  text: 'one',
                ),
                Tab(
                  text: 'two',
                ),
                Tab(
                  text: 'three',
                ),
              ],
              controller: tabController,
              onTap: (index) {
                setState(() {
                  selectedIndex = index;
                  tabController.animateTo(index);
                });
              },
            ),
            IndexedStack(
              children: <Widget>[
                Visibility(
                  child: Text('test1'),
                  maintainState: true,
                  visible: selectedIndex == 0,
                ),
                Visibility(
                  child: Text('test2'),
                  maintainState: true,
                  visible: selectedIndex == 1,
                ),
                Visibility(
                  child: Text('test3'),
                  maintainState: true,
                  visible: selectedIndex == 2,
                ),
              ],
              index: selectedIndex,
            ),
          ],
        ),
      ),
    );
  }
}

special thank's to @arbalest

11

based on @Yamin answer I used SizeBox Like below to get full page

    SizedBox.expand(
        child: TabBarView(),
      )

or any other size :

SizedBox(
        height: height:MediaQuery.of(context).size.height // or every other size ,
        child: TabBarView(),
      )
Shojaeddin
  • 1,851
  • 1
  • 18
  • 16
0

The error message in console mentions this: "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". Clearly, the horizontal viewport here is referring to the TabBarView widget which is not given a height constraint. So wrap both the TabBar and TabBarView widgets in Expanded widgets and give appropriate flex values to them to let them share their parent's height. Concretely,

DefaultTabController(
        length: 3,
        child: Column(
          children: <Widget>[
            Expanded(
              flex: 1,
              child: TabBar(
              tabs: <Widget>[
                Tab(
                  icon: Padding(
                    padding: EdgeInsets.all(6.0),
                    child: Image.asset(
                      "assets/images/icons/butterlike.png",
                      color: Colors.grey.shade800,
                    ),
                  ),
                ),
                Tab(
                  icon: Padding(
                    padding: EdgeInsets.all(6.0),
                    child: Image.asset(
                      "assets/images/icons/butterlike.png",
                      color: Colors.grey.shade800,
                    ),
                  ),
                ),
                Tab(
                  icon: Padding(
                    padding: EdgeInsets.all(6.0),
                    child: Image.asset(
                      "assets/images/icons/butterlike.png",
                      color: Colors.grey.shade800,
                    ),
                  ),
                ),
              ],
            ),
            ),
            Expanded(
              flex: 9,
              child: TabBarView(
              children: <Widget>[
                Container(
                  color: Colors.grey,
                ),
                Container(
                  color: Colors.green,
                ),
                Container(
                  color: Colors.purple,
                ),
              ],
            ),
            )
            
          ],
        ),
      )