Home > database >  Shrink list view when less items are present
Shrink list view when less items are present

Time:02-04

I'm trying to make a widget that displays two list view (one under the groups header, the other under the alerts header) with a minimum and maximum height.

I've managed to get maximum heights working via a ConstrainedBox wrapping everything however I've been unable to get a mimnimum height working. Idearly I would like the lists to like everything to shink if there are fewer items in both lists.

For example, in the screenshot below there are only two items in one list and none in the other so I would like the overall widget to shrink down to roughly half its current size

enter image description here

From what I can see in the Widget Inspector, the list itself is not taking up any more space than it needs however the Column appears to be taking up all the space the parent constraint is allowing for. I've tried messing with mainAxisSize: MainAxisSize.min, howeve this doesn't appear to have had any effect.

How can I prevent this column from taking all the extra space?

enter image description here

return ConstrainedBox(
  constraints: const BoxConstraints(maxHeight: 300, minHeight: 50),
  child: Row(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Flexible(
        flex: 1,
        child: Card(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              const Padding(padding: EdgeInsets.all(10), child: Text("Groups")),
              const Divider(),
              ListView.builder(
                  shrinkWrap: true,
                  itemCount: 2,
                  itemBuilder: (context, index) => ListTile(
                        ...
                      ))
            ],
          ),
        ),
      ),
      Flexible(
        flex: 1,
        child: Card(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              const Padding(padding: EdgeInsets.all(10), child: Text("Alerts")),
              const Divider(),
              ListView.builder(
                  shrinkWrap: true,
                  itemCount: 2,
                  itemBuilder: (context, index) => ListTile(
                        ...
                      ))
            ],
          ),
        ),
      ),
    ],
  ),
);

Edit after suggestions: enter image description here

CodePudding user response:

Try this

  • Remove crossAxisAlignment: CrossAxisAlignment.stretch from the row
  • Add mainAxisSize: MainAxisSize.min to the columns

Edit (in response to the comment):

To make the lists same size. Not sure if there is a straightforward way.

One hacky was I can think of is by setting the itemCount of both lists equal to the length of the list with most items. And in itemBuilder, return an empty ListTile when the index is out of available items to show. Example -

import 'dart:math';

const groupsCount = 2;
const alertsCount = 4;
final biggestCount = max(groupsCount, alertsCount);

Row(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Expanded(
      child: Card(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Padding(padding: EdgeInsets.all(10), child: Text("Groups")),
            const Divider(),
            ListView.builder(
              shrinkWrap: true,
              itemCount: biggestCount,
              itemBuilder: (_, index) {
                if (index < groupsCount) {
                  return ListTile(title: Text('Group $index'));
                } else {
                  return const ListTile();
                }
              },
            )
          ],
        ),
      ),
    ),
    Expanded(
      child: Card(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Padding(padding: EdgeInsets.all(10), child: Text("Alerts")),
            const Divider(),
            ListView.builder(
              shrinkWrap: true,
              itemCount: biggestCount,
              itemBuilder: (_, index) {
                if (index < alertsCount) {
                  return ListTile(title: Text('Alert $index'));
                } else {
                  return const ListTile();
                }
              },
            )
          ],
        ),
      ),
    ),
  ],
);

enter image description here

  • Related