0

I want the Expanded widget to have a minimum width (specified in flex) but it shall also increase its width if the child needs it. However, it only interprets flex as some kind of fixed width.

You can see it in the following screenshot.

Example Code:


Row(
  children: [
    Expanded(
      flex: 117,
      child: Widget(),
    ),
    Expanded(
      flex: 400,
      child: Widget(),
    ),
    Expanded(
      flex: 13,
      child: Widget(),
    ),
    Expanded(
      flex: 470,
      child: Widget(),
    ),
  ],
);

Screenshot: Screenshot

Tien Do Nam
  • 3,630
  • 3
  • 15
  • 30

4 Answers4

1

You can use constraint property of Container Widget. -I think-

You can try this:

Row(
  children: [
    Expanded(
      flex: 117,
      child: Container(
         constraints: BoxConstraints(minWidth: 40),
         child: Widget(),
      ),
    ),
    Expanded(
      flex: 400,
      child: Container(
         constraints: BoxConstraints(minWidth: 40),
         child: Widget(),
      ),
    ),
    Expanded(
      flex: 13,
      child: Container(
         constraints: BoxConstraints(minWidth: 40),
         child: Widget(),
      ),
    ),
    Expanded(
      flex: 470,
      child: Container(
         constraints: BoxConstraints(minWidth: 40),
         child: Widget(),
      ),
    ),
  ],
);

Edit 1: I created custom widget called MinHeightExpanded.

MinHeightExpanded Widget:

class MinHeightExpanded extends StatefulWidget {
  const MinHeightExpanded({
    Key? key,
    required this.minHeight,
    required this.flex,
    required this.color,
  }) : super(key: key);

  final double minHeight;
  final int flex;
  final Color color;

  @override
  _MinHeightExpandedState createState() => _MinHeightExpandedState();
}

class _MinHeightExpandedState extends State<MinHeightExpanded> {
  bool setToMin = false;

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) => setState(() {}));
    return !setToMin
        ? Expanded(
            flex: widget.flex,
            child: LayoutBuilder(
              builder: (BuildContext context, BoxConstraints boxConstraints) {
                print("${widget.color}: ${boxConstraints.maxHeight}");
                if (boxConstraints.maxHeight < widget.minHeight) {
                  setToMin = true;
                }
                return Container(
                  color: widget.color,
                );
              },
            ),
          )
        : Container(
            color: widget.color,
            height: widget.minHeight,
          );
  }
}

Use it like that:

     SizedBox(
        height: size.height,
        width: double.infinity,
        child: Column(
          mainAxisSize: MainAxisSize.max,
          children: [
            MinHeightExpanded(
              flex: 117,
              color: Colors.red,
              minHeight: 40,
            ),
            MinHeightExpanded(
              flex: 400,
              color: Colors.yellow,
              minHeight: 40,
            ),
            MinHeightExpanded(
              flex: 13,
              color: Colors.blue,
              minHeight: 400,
            ),
            MinHeightExpanded(
              flex: 470,
              color: Colors.green,
              minHeight: 40,
            ),
          ],
        ),
      ),
Hazar Belge
  • 1,009
  • 4
  • 20
1

If I underestand correctly, here is the answer to your question.

Use the Flexible widget instead of the Expanded. Flutter: Expanded vs Flexible

xbalaj
  • 977
  • 1
  • 8
  • 14
0

Why not just remove the Expanded for the child you want increase the width. Like

Row(
  children: [
    Expanded(
      flex: 117,
      child: Widget(),
    ),
    Expanded(
      flex: 400,
      child: Widget(),
    ),
    Widget(),
    Expanded(
      flex: 470,
      child: Widget(),
    ),
  ],
);

if you do not want to set the percentage, you can use IntrinsicWidth, like

    IntrinsicWidth(
        child: Row(children: [
      Widget(),
      Widget(),
      Widget(),
      Widget(),
    ]));

BUT, it is expensive

Sam Chan
  • 1,665
  • 4
  • 14
0

The answer by @HazarBelge does work, however I found a more elegant solution:

Component:

class PercentageRow extends StatelessWidget {

  final List<double> percentages;
  final List<Widget> children;

  const PercentageRow({required this.percentages, required this.children});

  @override
  Widget build(BuildContext context) {
    return Table(
      columnWidths: percentages.map((p) => IntrinsicColumnWidth(flex: p)).toList().asMap(),
      children: [TableRow(children: children)],
    );
  }
}

Usage:

PercentageRow(
    percentages: [0.3, 0.7],
    children: [
      Container(color: Colors.red, child: Text('A LOOOOOONG TEXT')),
      Container(color: Colors.green),
    ],
);
Tien Do Nam
  • 3,630
  • 3
  • 15
  • 30