5

I need to have some structure like this

enter image description here

I use LayoutBuilder to get the height of content (between App Bar and TabsBottomNavigation). Here i build Profile Info Container and want to build ListView with some List Tiles, but when I try to build it in Layout Builder I have errors in console.

enter image description here

If I create ListView out of LayoutBuilder it works!

Please help me to solve it. My code below:

Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints viewportConstraints) {
        return SingleChildScrollView(
          child: Container(
            child: Column(
              children: <Widget>[
                Container(
                  height: viewportConstraints.maxHeight * .44,
                  color: Theme.of(context).primaryColor,
                  padding: EdgeInsets.only(bottom: 2),
                  child: Align(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        _buildProfileImage(context),
                        SizedBox(height: 17),
                        Text(userName)
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: ListView(
                    children: <Widget>[
                      ListTile(
                        leading: Icon(Icons.print),
                        title: Text('asdad'),
                      )
                    ],
                  ),
                )
              ],
            ),
          ),
        );
      },
    );
  }
1
  • I have updated my answer, kindly check it. Commented Jun 24, 2019 at 11:38

5 Answers 5

4
+50

Use below build method will work in your case. (I have checked and it's working, so I hope it will work in your case also and will fit in your requirement.)

Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints viewportConstraints) {
        return Container(
          child: Column(
            children: <Widget>[
              Container(
                height: viewportConstraints.maxHeight * .44,
                color: Theme.of(context).primaryColor,
                padding: EdgeInsets.only(bottom: 2),
                child: Align(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      _buildProfileImage(context),
                      SizedBox(height: 17),
                      Text(userName),
                    ],
                  ),
                ),
              ),
              SizedBox(height: 16),
              Flexible(
                child: ListView(
                  children: <Widget>[
                    Card(
                      child: ListTile(
                        leading: Icon(Icons.print),
                        title: Text('asdad'),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        );
      },
    );
  }

I think SingleChildScrollView is of no use in this case so I removed it but you can use it if you fill so.

You still need to do some UI improvement as per your wish as this is the basic structure as per your requirement.

Hope this will help you.

Sign up to request clarification or add additional context in comments.

5 Comments

Works better, but i don't want to set height for Container that contains ListView Widget. I want to set it all free space without static height. If i remove height property i still have an error in console.
Updated my answer. Please check.
Wrap ListView in Flexible widget.
Can you help me with other question? stackoverflow.com/questions/56806117/…
@ulusoyca provide your detail answer instead of being a judge. This is not a genuine reason to down vote accepted answer with bounty.
2

You are using the LayoutBuilder in a wrong way.
It's supposed to be used to change the layout with the size of the device and/or orientation.

What you are trying to do is best accomplished with MediaQuery:

MediaQuery.of(context).padding.top //APP bar height
MediaQuery.of(context).padding.bottom //Bottom bar height
MediaQuery.of(context).size.height //Screen height

Comments

0
Widget build(BuildContext context) {
return Column(
    children:<Widget>[
     Expanded(
      child:LayoutBuilder(
      builder: (BuildContext context, BoxConstraints viewportConstraints) {
        return SingleChildScrollView(
          child: Container(
            child: Column(
              children: <Widget>[
                Container(
                  height: viewportConstraints.maxHeight * .44,
                  color: Theme.of(context).primaryColor,
                  padding: EdgeInsets.only(bottom: 2),
                  child: Align(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        _buildProfileImage(context),
                        SizedBox(height: 17),
                        Text(userName)
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: ListView(
                    children: <Widget>[
                      ListTile(
                        leading: Icon(Icons.print),
                        title: Text('asdad'),
                      )
                    ],
                  ),
                )
              ],
            ),
          ),
        );
      },
    ),
  ),
 ]
);
}

Comments

0
 Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints viewportConstraints) {
        return SingleChildScrollView(
          child: ListView(
            shrinkWrap: true,
            children: <Widget>[
             new Container(
                height: MediaQuery.of(context).size.height/3,
                color: Theme.of(context).primaryColor,
                padding: EdgeInsets.only(bottom: 2),
                child: Align(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      _buildProfileImage(context),
                      SizedBox(height: 17),
                      Text(userName)
                    ],
                  ),
                ),
              ),
             new ListView(
                shrinkWrap: true,
                children: <Widget>[
                  ListTile(
                    leading: Icon(Icons.print),
                    title: Text('asdad'),
                  )
                ],
              )
            ],
          ),
        );
      },
    );
  }

Comments

0

If you read the error log, it says non-zero flex incoming but constraints are unbounded. To understand that clearly, imagine Flutter is trying to draw pixels of something that not finite. That's the our problem.

Widgets like ListView or SingleChildScrollView are flex widgets and has no limits unlike Column or Row.

If you have children that sizes are not definite, then you have to define flex for your ListView. For that, you can use shrinkWrap or Flexible, Expanded widgets for both ListView itself or children.

And here is the my solution, simplified as much as possible:

Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints viewportConstraints) {
        return ListView(
          shrinkWrap: true, // That's it
          children: <Widget>[
            Container(
              color: Theme.of(context).primaryColor,
              height: viewportConstraints.maxHeight * .44,
              padding: EdgeInsets.only(bottom: 2),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  _buildProfileImage(context),
                  SizedBox(height: 17),
                  Text(userName)
                ],
              ),
            ),
            ListTile(
              leading: Icon(Icons.print),
              title: Text('asdad'),
            ),
            ListTile(
              leading: Icon(Icons.print),
              title: Text('asdad'),
            ),
            ListTile(
              leading: Icon(Icons.print),
              title: Text('asdad'),
            )
          ],
        );
      },
    );
  }

Meanwhile, you have too many children that does nothing. If you want different scrolling behavior inside the Profile Info and ListTiles parts, tell me because we will must create yet another ListView for achieve that.

Also if you share your buildProfileImage widget, we can optimize your code even further, because you may even not need the LayoutBuilder widget in this case.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.