Sizing Multiple ListView widgets in a Column in Flutter

Viewed 57

I have a Scaffold() with a body: of a Column() with two ListView() widgets...

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Title'),
      ),
      body: Column(
        children: [   
          List1(),
          List2(),

Each ListView is wrapped in an Expanded widget and populated with data from a StreamBuilder:

return StreamBuilder<QuerySnapshot?>(
        stream: stream-from-firebase
            .snapshots(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            List<List1> _list1 = [];
            for (var document in snapshot.data!.docs) {
              var name = List1.fromDoc(document);
              _list1.add(name);
            }
            return Expanded(
              child: ListView.builder(
                  itemCount: _list1.length,
                  itemBuilder: (context, index) {
                    return List1Tile(
                      data: _list1[index],
                    );
                  }),
            );
          } else {
            Container();
          }

This works, however Each List widget takes up half the screen, even if List1() is empty. It appears that wrapping List2() in an expanded widget is correct, however I'm unsure of what to do with List1() so that it takes up the minimal amount of space.

Edit: Wrapping List1() in a SizedBox() and defining the width: double.infinity, gives me the visual I'm after, however the following error is thrown:

'package:flutter/src/rendering/box.dart':
Failed assertion: line 1982 pos 12: 'hasSize'

My Question: How do I define the size of a ListView to dynamically resize itself?

Edit: For my purposes I wouldn't mind having a Single ListView with multiple streams populating it. Is this a possible solution as well?

Picture below (List1 is empty and still taking up half the screen):

enter image description here

1 Answers

So I made a working example that calculates flex ration based on ItemCount of each list (play with number to fit your app) and has a min (that can change) set to 10 to 5 flex

EXAMPLE:

enter image description here

Column(
      children: <Widget>[
        Expanded(
          flex: flexValue(1, listLenght1, listLenght2),
          child: Container(
            color: Colors.teal,
            child: ListView.builder(
                itemCount: listLenght1,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                      leading: const Icon(Icons.list),
                      trailing: const Text(
                        "TEST",
                        style: TextStyle(color: Colors.black, fontSize: 15),
                      ),
                      title: Text("List item $index"));
                }),
          ),
        ),
        Expanded(
          flex: flexValue(2, listLenght1, listLenght2),
          child: Container(
            color: Colors.orange,
            child: ListView.builder(
                itemCount: listLenght2,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                      leading: const Icon(Icons.list),
                      trailing: const Text(
                        "TEST",
                        style: TextStyle(color: Colors.black, fontSize: 15),
                      ),
                      title: Text("List item $index"));
                }),
          ),
        ),
      ],
    ),

And this is the function for calculating flex (optimization is needed) :

  int flexValue(int id, int itemcount1, int itemcount2) {
if (itemcount1 > 10 && itemcount2 > 10) {
  return 1;
}
if (itemcount1 < 7) {
  double difference = itemcount1 / itemcount2;
  difference *= 10;
  int temp = difference.round();
  if (temp < 5) {
    temp = 5;
  }

  if (id == 1) {
    return temp;
  } else {
    return 10;
  }
}
if (itemcount2 < 7) {
  double difference = itemcount2 / itemcount1;
  difference *= 10;
  int temp = difference.round();
  if (temp < 5) {
    temp = 5;
  }

  if (id == 2) {
    return temp;
  } else {
    return 10;
  }
}
return 1;

}

Related