How to make children of a Row have the same height by reading child constraints

289

This can be done cleverly using Stack instead, because the size of the Stack will match its non-positioned children, so it will automatically match your Text widget. Then use a Positioned widget to display the image - set both its top and bottom to 0 to make it stretch vertically, set right: 0 to make it align, and give it a fixed width.

demo using stack

Sample source code:

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Flutter Demo")),
      body: ListView(
        children: [
          for (int i = 8; i < 40; i += 6)
            Stack(
              children: [
                Padding(
                  padding: EdgeInsets.only(right: 100),
                  child: Text("Lorem ipsum " * i),
                ),
                Positioned(
                  top: 0,
                  bottom: 0,
                  right: 0,
                  width: 100,
                  child: Container(color: Colors.primaries[i % 10]),
                ),
              ],
            ),
        ],
      ),
    );
  }
}

Update:

You mentioned in the comments, you would want to enforce a "minimum height". You can easily do that in the Stack, by putting an invisible SizedBox, for example:

Stack(
  children: [
    Padding(
      padding: EdgeInsets.only(right: 100),
      child: Text("Lorem ipsum " * i),
    ),
    SizedBox(height: 100), // this forces minimum height
    Positioned(
      top: 0,
      bottom: 0,
      right: 0,
      width: 100,
      child: Container(color: Colors.primaries[i % 10]),
    ),
  ],
),

Result:

demo

Share:
289
shadysamir
Author by

shadysamir

Updated on January 01, 2023

Comments

  • shadysamir
    shadysamir over 1 year

    I have a SliverList with a delegate that returns Row for each item. The design requires this result:

    Desired layout

    The two children are Text and Image. The Image fir is BoxFit.cover and I am using Flexible to give them the desired width ratio. I need the image boundary height to match the text height only if the height is greater than or equal to width boundary (to keep it at least a square).

    First solution was to use LayoutBuilder to read the constraints of the image width and put the image in a ConstrainedBox with minHeight of LayoutBuilder->constraints->maxWidth.

    LayoutBuilder(
      builder: (context, constraints) => ConstrainedBox(
        constraints: BoxConstraints(
            minHeight: constraints.maxWidth,
            maxHeight: constraints.maxWidth),
        child: CachedNetworkImage(
            imageUrl: "https://via.placeholder.com/400x300",
            fit: BoxFit.cover,
          ),
      ),
    )
    

    All is well until the text is longer than image width, at this point the image remains a square and does not stretch to the full row height:

    Image height does not fill Row height

    Second solution was to wrap the Row in an IntrinsicHeight widget. But this means I can't use the LayoutBuilder inside it. So I removed the Layout builder and now I can't access the constraints to set the Image minHeight. The Image stretches very well to fill the full Row height. Until when the text is too short, which makes the image height go below its width:

    enter image description here

    How can I build this design to be responsive with variable text height?

  • shadysamir
    shadysamir over 2 years
    I already achieved this (see solution 2 in my question). The problem is to keep the container of both text and image at a minimum height of what the image width is right now so that the image is at least a square if not tall (first image in required design)
  • WSBT
    WSBT over 2 years
    @shadysamir Your "solution 2" uses IntrinsicHeight which will cause flutter to layout twice, inefficient. To enforce a "minimum height" you can simply add another SizedBox in the Stack, see my updated answer.
  • shadysamir
    shadysamir over 2 years
    You sent me in the right direction. Your answer was almost there. What was missing was responsiveness. Width available for image is not necessarily 100. I will write the answer I reached that solved it for me.