Reagankm
Reagankm

Reputation: 5419

How can I tightly wrap a Column of widgets inside a Card?

I have a page of my app that consists solely of a Card that holds a Column at the end of which is a MaterialList. Even if my list only has one or two items, the Card extends its vertical space to the bottom of the screen rather than stopping at the end of the list items. The Column documentation suggests this is normal Column behavior ("Layout each child a null or zero flex factor (e.g., those that are not Expanded) with unbounded vertical constraints"). I thought wrapping the list in a Flexible might achieve my desired effect but when I tried I got the following error:

RenderFlex children have non-zero flex but incoming height constraints are unbounded.
I/flutter (11469): When a column is in a parent that does not provide a finite height constraint, for example if it is
I/flutter (11469): in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a
I/flutter (11469): flex on a child (e.g. using a Flexible) indicates that the child is to expand to fill the remaining
I/flutter (11469): space in the vertical direction.
I/flutter (11469): These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child
I/flutter (11469): cannot simultaneously expand to fit its parent.

I'm clearly misunderstanding something about how this layout is supposed to work.

Here is sample code of what I have now as the body of the Scaffold for this page:

new Container(
// Outer container so we can set margins and padding for the cards
// that will hold the rest of the view.
alignment: FractionalOffset.topCenter,
margin: new EdgeInsets.only(top: style.wideMargin),
padding: new EdgeInsets.symmetric(horizontal: style.defaultMargin),
child: new Card(
  child: new Column(
    children: [
      new CustomHeader(), // <-- a Row with some buttons in it
      new Divider(),
      new MaterialList(
        type: MaterialListType.twoLine,
        children: listItems, // <-- a list of custom Rows
      ),
    ],
  ),
),

)

How can I have a Card that tightly wraps a Column of widgets?

Upvotes: 76

Views: 67338

Answers (4)

user3413723
user3413723

Reputation: 12233

For some reason mainAxisSize: min never seemed to work. I always got the stupid error that it didn't know what to do. To fix, I just resorted to ListView with shrinkWrap: true

return ListView(
  shrinkWrap: true,
  padding: const EdgeInsets.all(0),
  // background is red
  children: [
     ...
  ]
)

Upvotes: 1

Willey Hute
Willey Hute

Reputation: 1078

If Row or Column is your root widget, use MainAxisSize.min on root widget.

If Another widget is the root, then wrap that root widget in Center widget.

Upvotes: 2

Jitesh Mohite
Jitesh Mohite

Reputation: 34220

Wrap widget may come to rescue if anyone wants to shrink its list, which exacts similar to @Adam answer

body: Container(
        child: Card(
          child: Wrap(
            direction: Axis.vertical,
            spacing: 10,
            children: <Widget>[
              Text('One'),
              Text('Two'),
              Text('Three'),
              Text('Four'),
            ],
          ),
        ),
      ), 

but this Wrap can do the job of both Row & Column if you add Column for Axis.vertical & Row for Axis.Horizontal. Also you can add equal spacing to all inbetween widgets which is missing in Column & Row

Upvotes: 9

Adam Barth
Adam Barth

Reputation: 1789

By default, Column expands to fill the maximum vertical space. You can change this behavior by setting the mainAxisSize property to MainAxisSize.min, which causes the Column to take up only the minimum amount of vertical space it needs to fit its children.

Upvotes: 169

Related Questions