Home > Software design >  Flutter/'RenderShrinkWrappingViewport does not support' error with Table
Flutter/'RenderShrinkWrappingViewport does not support' error with Table

Time:07-13

I want to put a locked ListView inside a TableCell, but I get the error. How do I fix this? Since the error is the same, I'm substituting ListView, but the actual code uses MasonryGridView.count(), so I can't use Row, and then I want the width of the Cell to match the length of the List, so I can't specify it either.

class TableTest2 extends StatelessWidget {
  const TableTest2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    List<String> data = ['1', '2', '3'];

    return Scaffold(
      body: Center(
        child: Table(
          columnWidths: const {0: IntrinsicColumnWidth()},
          defaultVerticalAlignment: TableCellVerticalAlignment.middle,
          children: [
            TableRow(
              children: [
                SizedBox(
                  height: 80,
                  child: ListView.builder(
                    shrinkWrap: true,
                    scrollDirection: Axis.horizontal,
                    physics: const NeverScrollableScrollPhysics(),
                    itemCount: data.length,
                    itemBuilder: (_, i) => Chip(label: Text(data[i])),
                  ),
                )
              ],
            ),
          ],
        ),
      ),
    );
  }
}

this is error message.

The following assertion was thrown during performLayout():
RenderShrinkWrappingViewport does not support returning intrinsic dimensions.
Calculating the intrinsic dimensions would require instantiating every child of the viewport, which
defeats the point of viewports being lazy.
If you are merely trying to shrink-wrap the viewport in the main axis direction, you should be able to achieve that effect by just giving the viewport loose constraints, without needing to measure its
intrinsic dimensions.

CodePudding user response:

The issue is coming from using IntrinsicColumnWidth, you can choose other classes like FixedColumnWidth, FractionColumnWidth... or create new class with extending TableColumnWidth

child: Table(
  columnWidths: const {
    // 0: IntrinsicColumnWidth(), // remove/replace this
  },

CodePudding user response:

What the error means is that a parent widget is trying to do some logic on its children sizes ("intrinsic dimensions") but one of the children doesn't support returning those "intrinsic dimensions".

Here, I guess Table is the one that checks the intrinsic dimensions, and ListView.builder is the one that doesn't support returning intrinsic dimensions.

A way you can solve it is to use a SingleChildScrollView and a Column:

class TableTest2 extends StatelessWidget {
  const TableTest2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    List<String> data = ['1', '2', '3'];

    return Scaffold(
      body: Center(
        child: Table(
          columnWidths: const {0: IntrinsicColumnWidth()},
          defaultVerticalAlignment: TableCellVerticalAlignment.middle,
          children: [
            TableRow(
              children: [
                SizedBox(
                  height: 80,
                  child: SingleChildScrollView(
                    scrollDirection: Axis.horizontal,
                    physics: const NeverScrollableScrollPhysics(),
                    child: Column(
                      children: data.map((data) => Text(data)).toList(),
                    ),
                  ),
                )
              ],
            ),
          ],
        ),
      ),
    );
  }
}

or you can keep your ListView.builder, but you will have to remove

columnWidths: const {0: IntrinsicColumnWidth()},

What was happening?

In flutter, you are not supposed to do any logic with sizes when building the widget tree, you only have access to the constraints. This this documentation.

Constraints go down. Sizes go up. Parent sets position.

This is a design choice made to make the layout of the widget tree performant since it has to go through the widget tree only once.

However, there are still some widgets that apply some logic from the size of their children (like IntrinsicHeight) but it comes with a cost it renders the layout more than once:

This class is relatively expensive, because it adds a speculative layout pass before the final layout phase. Avoid using it where possible. In the worst case, this widget can result in a layout that is O(N²) in the depth of the tree.

When you try to use the IntrinsicColumnWidth with your Table, the Table will try to layout each child several times, look at their sizes, and then decide what is the best one.

However ListView.builder is lazy (see this documentation), so it doesn't render all its children, only the ones you can see on the screen. This is also done for performances (think about the case where you have an infinite number of children). It means the ListView.builder cannot know its size because it cannot render all its children. Therefore, it doesn't support returning intrinsic dimensions as your error states.

  • Related