Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set height of child elements equal to highest other element that are contained by Wrap Widget (Flutter)

Tags:

flutter

I need to have box alignment like on image below. I use Wrap Widget to wrap my items by two elements in a row. But as i see Wrap widget don't have stretch property for the crossAxisAlignment.

I use another method to build cardItem, to simplify my code, and re-use it for my four cards. Maybe you know some other Widgets to help to do it.

enter image description here

Can someone help me with it. Please see my code below:

class Transfers extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Transfers'),
      ),
      body: Center(
        child: Wrap(
          spacing: 10,
          runSpacing: 10,
          children: <Widget>[
            _buildTransferItem(
              "assets/images/icon.png",
              "Some Text of this box",
              context,
            ),
            _buildTransferItem(
              "assets/images/icon.png",
              "Text",
              context,
            ),
            _buildTransferItem(
              "assets/images/icon.png",
              "Some Text of this box",
              context,
            ),
            _buildTransferItem(
              "assets/images/icon.png",
              "Some Text of this box",
              context,
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildTransferItem(
      String transferIcon, String transferTitle, BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width * 0.5 - 20,
      height: ,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12.0),
        boxShadow: [
          BoxShadow(
            color: Color.fromRGBO(140, 140, 140, 0.5),
            blurRadius: 6.0,
          )
        ],
      ),
      padding: EdgeInsets.symmetric(
        vertical: screenAwareSize(20.0, context),
        horizontal: screenAwareSize(20.0, context),
      ),
      child: Column(
        children: <Widget>[
          Image.asset(
            transferIcon,
            width: screenAwareSize(72.0, context),
            height: screenAwareSize(39.0, context),
          ),
          SizedBox(height: screenAwareSize(7.0, context)),
          Text(
            transferTitle,
            style: TextStyle(
              fontSize: screenAwareSize(14, context),
              fontWeight: FontWeight.w300,
            ),
            textAlign: TextAlign.center,
          )
        ],
      ),
    );
  }
}
like image 304
Andrew Kovalchuk Avatar asked Jun 28 '19 11:06

Andrew Kovalchuk


People also ask

How do you find the height of a child Widget widget flutter?

How do I find the size of a widget in flutter? To get the size/position of a widget on screen, you can use GlobalKey to get its BuildContext to then find the RenderBox of that specific widget, which will contain its global position and rendered size.

What does the wrap () widget do?

A widget that displays its children in multiple horizontal or vertical runs. A Wrap lays out each child and attempts to place the child adjacent to the previous child in the main axis, given by direction, leaving spacing space in between.

Which of the following helps you to set a specific width and or height between widget in flutter?

A better approach is using Container widget. When you need to change width, height or add padding/margin to any widget you should wrap the target widget into a container. The container widget is for this kind of job.


2 Answers

What you need is InstrinsicHeight widget. Here is an example of how to solve your problem for any given number of cards in row. As you can see the _generateRows(List<String> labels, int numPerRow) function gets a collection of card labels and a number of cards in a row as input parameters and generates the layout:

  List<Widget> _generateRows(List<String> labels, int numPerRow) {
    Widget _buildTransferItem(String transferTitle, int numPerRow) {
      return Builder(
        builder: (context) {
          return Container(
            width: MediaQuery.of(context).size.width / numPerRow - 20,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(12.0),
              boxShadow: [
                BoxShadow(
                  color: Color.fromRGBO(140, 140, 140, 0.5),
                  blurRadius: 6.0,
                )
              ],
            ),
            padding: EdgeInsets.symmetric(
              vertical: 20,
              horizontal: 20,
            ),
            child: Column(
              children: <Widget>[
                Icon(
                  Icons.info,
                  size: 48,
                ),
                SizedBox(height: 7),
                Text(
                  transferTitle,
                  style: TextStyle(
                    fontSize: 14,
                    fontWeight: FontWeight.w300,
                  ),
                  textAlign: TextAlign.center,
                )
              ],
            ),
          );
        },
      );
    }

    List<Widget> result = [];
    while (labels.length > 0) {
      List<String> tuple = labels.take(numPerRow).toList();
      for(int i = 0; i< tuple.length; i++){
        if (labels.length > 0) labels.removeAt(0);
      }
      Widget item = IntrinsicHeight(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: tuple.map((s) => _buildTransferItem(s, numPerRow)).toList(),
        ),
      );
      result.add(item);
    }
    return result
        .expand((item) => [
              item,
              SizedBox(
                height: 20,
              ),
            ])
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Transfers'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: _generateRows(
            ["Some text of this box", "Text", "Some Text of this box", "Some Rather Long Text of this box", "Cool, yeah?", "Last"],
            3,
          ),
        ),
      ),
    );
  }

The IntrinsicHeight widget takes into consideration intrinsic dimensions of the child which for most container widgets like Row, etc. will be definite numbers. But it comes with performance warranty of O(N^2) in complex cases as you may read in the API docs. Here are screenshots of cases when number of cards per row are 2 and 3. Please note that this parameter is passed just once and is not hardcoded anywhere.

enter image description here

If there's an odd number of items it will center last item:

enter image description here

enter image description here

like image 100
Alexander Arendar Avatar answered Oct 27 '22 08:10

Alexander Arendar


The way you are applied width of Container using media Query. Same way you can apply for Height or you can write manual for example

height: 300.0,

And to match parent of Column you can write following code :

 Column(
mainAxisSize: MainAxisSize.max, // match parent
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <widget>[
  // your widget
]
like image 43
Dhavalketu Darji Avatar answered Oct 27 '22 08:10

Dhavalketu Darji