31

I am developing a Flutter application and I want to dynamically adjust the height of the ListView.

I want the list to have a maximum height of 200. If the height is more than that, user will have to scroll to reach the bottom. If height is below 200, it will take only as much space as needed.

Preview of application: Screenshot. As you can see Restaurants nearby is pushed to the very bottom of the page. I want the ListView to only take height of 200 or less so that the content below isn't pushed to the bottom.

Here is my current code:

@override
Widget build(BuildContext context) {
  return Container(
    padding: EdgeInsets.all(10.0),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text(
          'Restaurants nearby',
          style: TextStyle(
            fontSize: 20.0,
            fontWeight: FontWeight.bold,
          ),
        ),
        Divider(),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text('Enter restaurant manually'),
              onPressed: () {
                print('Button pressed');
              },
            ),
          ],
        ),
        Flexible(
          child: ListView.builder(
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                leading: CircleAvatar(
                  backgroundColor: Colors.cyan,
                ),
                title: Text('Test restaurant'),
                subtitle: Text('80m'),
              );
            },
            itemCount: 15,
          ),
        ),
        Text(
          'Restaurants nearby',
          style: TextStyle(
            fontSize: 20.0,
            fontWeight: FontWeight.bold,
          ),
        ),
      ],
    ),
  );
}
1
  • Hi @Bill, Did you resolve this issue? Commented Nov 25, 2021 at 3:17

8 Answers 8

40

You are using Flexible widget, that's why your ListView expands. You have to change Flexible to ConstrainedBox and add shrinkWrap: true to your ListView.

ConstrainedBox(
  constraints: BoxConstraints(maxHeight: 200, minHeight: 56.0),
  child: ListView.builder(
    shrinkWrap: true,
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          leading: CircleAvatar(
            backgroundColor: Colors.cyan,
          ),
          title: Text('Test restaurant'),
          subtitle: Text('80m'),
        );
      },
    itemCount: 15,
  ),
),

More info here: https://api.flutter.dev/flutter/widgets/ConstrainedBox-class.html

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

2 Comments

The height is not dynamic in this case. If ListView has height less than 200, then SizedBox will still take height of 200. I don't want that. I want to have height automatically adjusted based on the height of the list, but not more than 200. If it is more than 200, then user has to scroll to reach the bottom of ListView.
ConstrainedBox doesn't answer the question, LimitedBox does
22

You can use LimitedBox

Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: <Widget>[
    Text(...),
    Divider(),
    Row(...),
    LimitedBox(
      maxHeight: 200.0,
      child: ListView.builder(...),
    ),
    Text(...),
  ],
),

Recommended solution in case when the incoming constraints are unbounded

Comments

8

Consider wrapping the ListView into this

LimitedBox(
  maxHeight: 200,
  child: Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      Flexible(
        child: ListView.builder(
          shrinkWrap: true,
          itemBuilder: (BuildContext context, int index) {
            return ListTile(
              leading: CircleAvatar(
                backgroundColor: Colors.cyan,
              ),
              title: Text('Test restaurant'),
              subtitle: Text('80m'),
            );
          },
          itemCount: _itemsCount,
        ),
      ),
    ]
  )
),

Note that:

  • shrinkWrap of ListView is set to true
  • mainAxisSize of Column is set to MainAxisSize.min
  • maxHeight of LimitedBox is set to 200

A complete snippet:

import 'package:flutter/material.dart';

class DebugWidget extends StatefulWidget {
  @override
  _DebugWidgetState createState() => _DebugWidgetState();
}
class _DebugWidgetState extends State<DebugWidget> {
  int _itemsCount = 1;

  @override
  Widget build(BuildContext context) {
    Widget child = Container(
      padding: EdgeInsets.all(10.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(
            'Restaurants nearby',
            style: TextStyle(
              fontSize: 20.0,
              fontWeight: FontWeight.bold,
            ),
          ),
          Divider(),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              RaisedButton(
                child: Text('Enter restaurant manually'),
                onPressed: () {
                  print('Button pressed');
                },
              ),
              RaisedButton(
                child: Text('+1'),
                onPressed: () {
                  setState(() {
                    _itemsCount += 1;
                  });
                },
              ),
              RaisedButton(
                child: Text('-1'),
                onPressed: () {
                  setState(() {
                    _itemsCount -= 1;
                  });
                },
              ),
            ],
          ),
          LimitedBox(
            maxHeight: 200,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Flexible(
                  child: ListView.builder(
                    shrinkWrap: true,
                    itemBuilder: (BuildContext context, int index) {
                      return ListTile(
                        leading: CircleAvatar(
                          backgroundColor: Colors.cyan,
                        ),
                        title: Text('Test restaurant'),
                        subtitle: Text('80m'),
                      );
                    },
                    itemCount: _itemsCount,
                  ),
                ),
              ]
            )
          ),
          Text(
            'Restaurants nearby',
            style: TextStyle(
              fontSize: 20.0,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    );

    return Scaffold(
      body: child,
    );
  }
}

Comments

6

I found a solution to this problem. you should wrap your ListView with LimittedBox or ConstraintBox and give them maxHeight and set shrinkWrap property of ListView to true. the solution would be something like this.

LimitedBox(
          maxHeight: 200,
          child: ListView.builder(
            shrinkWrap: true,
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                leading: CircleAvatar(
                  backgroundColor: Colors.cyan,
                ),
                title: Text('Test restaurant'),
                subtitle: Text('80m'),
              );
            },
            itemCount: 15,
          ),
        ),

Comments

3

I see that this question has never been answered only with giving a fixed height, so here is what works for me.

For some reason if you set the shrinkwrap to true it doesn't look like it is working but it does, the problem is in the padding settings of the ListView, set the padding to edgeinstets.zero. That fixes it for me.

  • Wrap inside a Flexible
  • ShrinkWrap true
  • Padding, zero
  • and if needed the column to MainAxisSize.min.

Hope it helps some people.

Example of my code:

Flexible(
                  child: Container(
                    decoration: BStyles.cardDecoration1,
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          const Text(
                            'PRODUCTION TASKS',
                          ),
                          const SizedBox(
                            height: textVerticalSpacing,
                          ),
                          Flexible(
                            child: ListView.builder(
                              itemCount: recentTasks.length,
                              padding: EdgeInsets.zero,
                              physics: const NeverScrollableScrollPhysics(),
                              shrinkWrap: true,
                              itemBuilder: (BuildContext context, int index) {
                                return TaskCard(
                                  task: recentTasks[index],
                                  widthInfo: MediaQuery.of(context).size.width * 0.6,
                                );
                              },
                            ),
                          ),
                          const SizedBox(
                            height: itemSpacing,
                          ),
                          Align(
                            alignment: Alignment.centerRight,
                            child: InkWell(
                              onTap: () { },
                              child: const Text(
                                'View more',
                              ),
                            ),
                          ),
                          const SizedBox(
                            height: textVerticalSpacing,
                          ),
                        ],
                      ),
                    ),
                  ),
                ),

Comments

1
ConstrainedBox(
  constraints: BoxConstraints(maxHeight: 200.0),
  child: [your child here],
)

This make your child's height not bigger than 200.0

1 Comment

If we define minHeight then, how it restricts the maxHeight ?
0

What was preventing mine from sizing dynamically was having it inside a Scaffold. Once I removed the Scaffold it worked. I didn't have a maximum height requirement for mine so to make it size dynamically all I had to do was set shrinkWrap to true and put it inside a Flexible widget. eg.

Column(
  children: [
    Flexible(
      ListView.separated(shrinkWrap: true, ...)
    )
  ]
)

Comments

-1

You can always size the ListView container as % of the viewport (assuming of course that the other widgets also are sized in the same manner):

return Container(
      height: MediaQuery.of(context).size.height * 0.75,
      child: ListView.builder(
        itemBuilder: (ctx, index) {
          return Card(...

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.