2

I have a Flutter Widget with a column layout that has two Containers, one of which has a ListView.builder. When the page renders I get a

bottom overflow by 169px

and I'm not sure how to fix it.

I've googled around for solutions and have tried various things like wrapping one or more of the Containers in the widget in an Expanded widget, but that doesn't work either. If I wrap just the Container that has the FutureBuilder inside of it in an Expanded, then the ListView doesn't render at all and I see errors like:

I/flutter ( 3516): Another exception was thrown: RenderFlex children have non-zero flex but incoming height constraints are unbounded.
I/flutter ( 3516): Another exception was thrown: RenderBox was not laid out: RenderFlex#0caf9 relayoutBoundary=up2 NEEDS-PAINT
I/flutter ( 3516): Another exception was thrown: RenderBox was not laid out: RenderFlex#963f4 relayoutBoundary=up1 NEEDS-PAINT
I/flutter ( 3516): Another exception was thrown: NoSuchMethodError: The method '<=' was called on null.

This is what the build function of my Widget looks like:

  Widget build(BuildContext context) {
    return Container(
        child: Column(children: <Widget>[
      Container(
          height: 40,
          color: Colors.grey.withOpacity(0.5),
          child: Padding(
              padding: const EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0),
              child: TextField(
                  autofocus: false,
                  controller: searchFilterController,
                  keyboardType: TextInputType.text,
                  maxLines: 1,
                  decoration: InputDecoration(
                      border: InputBorder.none,
                      filled: true,
                      fillColor: Colors.white.withOpacity(1),
                      hintText: 'Search',
                      suffixIcon: Icon(
                        Icons.search,
                        color: Colors.grey,
                      )),
                  onChanged: (value) {
                    filter = value;
                  }))),

      Container(
          child: FutureBuilder<UserPantry>(
        future: UserPantryDao.getUserPantry(widget.userId),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            widget.ingredientList.clear();
            if (filter == null || filter.trim() == "") {
              widget.ingredientList.addAll(snapshot.data.ingredients);
            } else {
              for (UserIngredient ingredient in snapshot.data.ingredients) {
                if (ingredient.ingredient.name
                    .toLowerCase()
                    .contains(filter.toLowerCase())) {
                  widget.ingredientList.add(ingredient);
                }
              }
            }

            return ListView.builder(
                shrinkWrap: true,
                itemCount: widget.ingredientList.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                      title: Text(
                    widget.ingredientList[index].ingredient.name,
                    style: TextStyle(fontSize: 20.0),
                  ));
                });
          } else if (snapshot.hasError) {
            print(snapshot.error);
            return Text(
                "An error occurred while loading your pantry. Please try again.");
          }
          //By default just show an empty container.
          return Container();
        },
      ))
    ]));
  }

4 Answers 4

3

Try remove the Container outside, and wrap the list in a expanded. As @Miguel Ruivo answered, ListView must have a bounded constraints.

Widget build(BuildContext context) {
    return Column(children: <Widget>[
      Container(
          height: 40,
          color: Colors.grey.withOpacity(0.5),
          child: Padding(
              padding: const EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0),
              child: TextField(
                  autofocus: false,
                  controller: searchFilterController,
                  keyboardType: TextInputType.text,
                  maxLines: 1,
                  decoration: InputDecoration(
                      border: InputBorder.none,
                      filled: true,
                      fillColor: Colors.white.withOpacity(1),
                      hintText: 'Search',
                      suffixIcon: Icon(
                        Icons.search,
                        color: Colors.grey,
                      )),
                  onChanged: (value) {
                    filter = value;
                  }))),
      Expanded(
          child: FutureBuilder<UserPantry>(
        future: UserPantryDao.getUserPantry(widget.userId),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            widget.ingredientList.clear();
            if (filter == null || filter.trim() == "") {
              widget.ingredientList.addAll(snapshot.data.ingredients);
            } else {
              for (UserIngredient ingredient in snapshot.data.ingredients) {
                if (ingredient.ingredient.name
                    .toLowerCase()
                    .contains(filter.toLowerCase())) {
                  widget.ingredientList.add(ingredient);
                }
              }
            }

            return ListView.builder(
                shrinkWrap: true,
                itemCount: widget.ingredientList.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                      title: Text(
                    widget.ingredientList[index].ingredient.name,
                    style: TextStyle(fontSize: 20.0),
                  ));
                });
          } else if (snapshot.hasError) {
            print(snapshot.error);
            return Text(
                "An error occurred while loading your pantry. Please try again.");
          }
          //By default just show an empty container.
          return Container();
        },
      ))
    ]);
  }
Sign up to request clarification or add additional context in comments.

Comments

3

Simply Wrap the List only with Expanded. Try this:

Column(
            children: [
              Container(
                child: Text("data"),
                color: Colors.redAccent,
              ),
              Expanded(child: ListView.builder(itemBuilder: (context, i) {
                return Text("data");
              })),
            ],
          ),

Comments

0

Just wrap your FutureBuilder<UserPantry> in an Expanded widget and remove the Container because you don't need it at all here.

 Expanded(
        child: FutureBuilder<UserPantry>(
           future: UserPantryDao.getUserPantry(widget.userId),
   ...

This happens because you're giving unbounded constraints to the ListView. Another option, would be adding some height constraint to the ListView parent, such as setting the height in the Container to something.

4 Comments

That was one of the things I tried already, but when I do that the whole page is blank and I see these errors in the console: I/flutter ( 5471): Another exception was thrown: RenderBox was not laid out: RenderFlex#350b4 relayoutBoundary=up2 NEEDS-PAINT I/flutter ( 5471): Another exception was thrown: RenderBox was not laid out: RenderFlex#3fe57 relayoutBoundary=up1 NEEDS-PAINT I/flutter ( 5471): Another exception was thrown: NoSuchMethodError: The method '<=' was called on null.
I don’t have your whole tree. As you’ve it right now, it should work. Anyway, just set some height to the Container and you should be fine.
Setting a height on the container does resolve the issue, but how will I know what height to use? Won't it vary from device to device?
Yes, but you can use a %, by doing MediaQuery.of(context).size.height * 0.5, this will set your ListView to use 50% of the screen height. However, with Expanded you shouldn't need this, and it should work as well, because you'll expand to fill the viewport vertically.
0

Wrapping ListView.separated( separatorBuilder: (context, index) => Divider(), ...) in Expanded will solve your issue.

Eg: Expanded(child: ListView.separated(separatorBuilder: (context, index) =>Divider(),itemCount: 1, itemBuilder: (context, index) {return Container(height:200.0, child: ...);})

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.