ListView in LimitedBox vs ConstrainedBox

Viewed 979

While trying to figure out how to limit the size of a ListView, I saw examples in Stackoverflow suggesting that doing something like placing the ListView in a LimitedBox and setting the maxHeight of the Limited box and the shrinkwrap of the ListView, would accomplish it. However, the ListView would still grow past the maxheight to accommodate the size of the children in the ListView.

Eventually, I tried an example using ConstrainedBox and setting it's maxHeight and the Shrinkwrap of the ListView; doing this seemed to accomplish the intended result of limiting the Listview height to the maxHeight setting.

Can someone help me understand why LimitedBox maxHeight does not work in this case, when ConstrainedBox does?

Here is an example of the LimitedBox that is not constraining itself to the maxHeight:

Widget _getPopupCard(){
    return Hero(
      tag: 0,
      createRectTween: (begin,end){
        return MaterialRectCenterArcTween(begin: begin, end: end);
      },
      child: Container(
        child:Padding(
          padding: EdgeInsets.all(14), 
          child: Material(
            borderRadius: BorderRadius.circular(18), 
            color: Colors.white, 
            child:  LimitedBox(
            maxHeight: 300,
              child: ListView(
                shrinkWrap: true,
                  children:  _getTiles(),
                ),
            ),
            ),
          ),
        ),
    );
  }

Here is an example of the ConstrainedBox version that does limit itself to the maxHeight:

Widget _getPopupCard(){
  return Hero(
    tag: 0,
    createRectTween: (begin,end){
      return MaterialRectCenterArcTween(begin: begin, end: end);
    },
    child: Container(
      child:Padding(
        padding: EdgeInsets.all(14), 
        child: Material(
          borderRadius: BorderRadius.circular(18), 
          color: Colors.white, 
          child:  ConstrainedBox(
            constraints: BoxConstraints(maxHeight: 300.0),
            child: ListView(
              shrinkWrap: true,
              children:  _getTiles(),
            ),
          ),
        ),
      ),
    ),
  );
}
1 Answers

https://api.flutter-io.cn/flutter/widgets/LimitedBox-class.html

LimitedBox : A box that limits its size only when it's unconstrained.

ConstrainedBox : which applies its constraints in all cases, not just when the incoming constraints are unbounded.

LimitedBox can only works when parent is unconstrainted and flutter cannot render infinity width/heigh, so LimitedBox must both provide MaxWidth and MaxHeight

You can wrap UnconstrainedBox to make LimitedBox works, but you really don't need this... see: https://www.woolha.com/tutorials/flutter-using-limitedbox-widget-examples

https://dartpad.dev/2cfc997a7984bf848687f209cba917ce?null_safety=true

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'LimitedBox',
      home: Scaffold(
        appBar: AppBar(
            title:
                Text('LimitedBox can only work when parent is unconstrainted')),
        body: Center(
          child: UnconstrainedBox( // wrap UnconstrainedBox to make LimitedBox works, but you really don't need this... https://www.woolha.com/tutorials/flutter-using-limitedbox-widget-examples
            child: _getPopupCard(),
          ),
        ),
      ),
    );
  }
}

Widget _getPopupCard() {
  return LimitedBox(
    maxHeight: 300.0,
    maxWidth: 300.0,
    child: ListView(
      shrinkWrap: true,
      children: _getTiles(),
    ),
  );
}

List<Widget> _getTiles() {
  return List.generate(100, (int i) => i).map((int i) {
    return Container(
      color: i % 2 == 0 ? Colors.red : Colors.green,
      child: Center(child: Text("$i")),
    );
  }).toList();
}

update:

Is Container the constrained parent that is overriding the LimitedBox even though I didn't set height or width on the Container?

I search this question just because I'm reading this guide: https://flutter.dev/docs/development/ui/layout/constraints Container's layout behavior is little complex.

About this, I've run code below , seems flutter will give Container a default Constraints. The Container source tells something, maybe you should get some info from the source.

  runApp(
    MaterialApp(
      home: UnconstrainedBox(
        child: LayoutBuilder(
          builder: (ctx, Constraints constraints) {
            print(ctx);
            print(constraints);//BoxConstraints(unconstrained)
            return Text("hello world");
          },
        ),
      ),
    ),
  );

  runApp(
    MaterialApp(
      home: Container(
        color: Colors.white,
        child: LayoutBuilder(
          builder: (ctx, constraints) {
            print(ctx);
            print(constraints); // BoxConstraints(w=500.0, h=296.0)
            return Text("hello world333333");
          },
        ),
      ),
    ),
  );
Related