Search code examples
flutterflutter-listviewflutter-container

Weird behavior of Flutter list-view. It overflows its bounds


I observed some weird behavior of Flutter's list view. It overflows it's boundary. I basically needed a screen with a heading area, a list-view in the middle and a footer. I enclosed the three sections each in a SizedBox. However, the listview overflows its sized box while repainting. Below is the code I used and see the screenshot of what I observe.

// ignore_for_file: avoid_print

import 'package:flutter/material.dart';

class TestData {
  String name;
  String description;

  TestData({required this.name, required this.description});

  @override
  String toString() {
    return "name: $name description: $description";
  }
}

final List<TestData> testData = [
  TestData(name: "Item 1", description: "description for item 1"),
  TestData(name: "Item 2", description: "description for item 1"),
  TestData(name: "Item 3", description: "description for item 1"),
  TestData(name: "Item 4", description: "description for item 1"),
  TestData(name: "Item 5", description: "description for item 1"),
  TestData(name: "Item 6", description: "description for item 1"),
  TestData(name: "Item 7", description: "description for item 1"),
  TestData(name: "Item 8", description: "description for item 1"),
  TestData(name: "Item 9", description: "description for item 1"),
];

class ListWithHeader extends StatelessWidget {
  const ListWithHeader({super.key});

  Widget _header(BuildContext context) {
    return const Text("This is the header");
  }

  Widget _footer(BuildContext context) {
    return Container(
        alignment: Alignment.center,
        color: Colors.green.shade100,
        child: const Text("This is the footer"));
  }

  Widget _listBody(BuildContext context) {
    print("Item count :$testData.length");
    return ListView.separated(
      itemCount: testData.length,
      separatorBuilder: (context, index) => const Divider(),
      itemBuilder: (context, index) {
        TestData td = testData[index];
        print("ListTile for index $index and td: $td");
        return ListTile(
          title: Text(td.name),
          subtitle: Text(td.description),
          tileColor: Colors.pink.shade100,
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("ListWithHeader"),
      ),
      body: LayoutBuilder(
        builder: (context, constraints) {
          return SizedBox(
            height: constraints.maxHeight,
            child: Column(
              children: [
                SizedBox(
                  height: constraints.maxHeight * .2,
                  child: Container(
                      //alignment: Alignment.center,
                      color: Colors.white,
                      child: _header(context)),
                ),
                Expanded(
                  //height: constraints.maxHeight * 0.5,
                  child: _listBody(
                      context), //_bodyText(context) //_listBody(context),
                ),
                SizedBox(
                    height: constraints.maxHeight * 0.2,
                    child: _footer(context)),
              ],
            ),
          );
        },
      ),
    );
  }
}

Anyone know if I am doing something wrong or is this a bug?

Screenshot showing ListView overflow


Solution

  • first, using LayoutBuilder is unnecessary.

        return Scaffold(
          appBar: AppBar(
            title: const Text("ListWithHeader"),
          ),
          body: Column(
            children: [
              Expanded(
                child: Container(
                  alignment: Alignment.center,
                  color: Colors.white,
                  child: _header(context),
                ),
              ),
              Expanded(
                flex: 3,
                child: _listBody(context),
              ),
              Expanded(
                child: _footer(context),
              ),
            ],
          ),
        );
    

    second, try adding padding: EdgeInsets.zero to the ListView