C. Mürtz
C. Mürtz

Reputation: 504

Flutter: row cross axis expand

Is there any way to give a specific widget the height of the highest widget in the row? I don't want to stretch the row on the cross axis. I just want all widgets to have the height of the highest widget.

Upvotes: 27

Views: 14055

Answers (2)

Roddy R
Roddy R

Reputation: 1470

There are a number of things to consider.

Parent of Row Constrained

IntrinsicHeight would only work if "unlimited height is available". Conversely, if the parent of the Row is constrained, it would not work DartPad.

  • If what you want to do is extend the widgets height to match the parent simply do:
Row(
 crossAxisAlignment: CrossAxisAlignment.stretch,
 ...
)

It will make all widgets the same height, even if you set row's children height unequal. It will ignore children's height and will not make the other widgets the same as the tallest.

Parent of Row Unconstrained

  • If you know the height of the tallest widget beforehand, simply constraint the parent of the Row with that height with SizedBox.
  • If not, but you know the aspect ratio, use AspectRatio instead it is a much cheaper widget.
AspectRatio(
        aspectRatio: 2, // try diff numbers
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.stretch,
)
  • If you still don't know any of that which is rarely the case there are a few other options to implement the layout by hand with LayoutBuilder or creating a new widget.
  • If none of that work use IntrinsicHeight as parent of Row as a last resort since it is supposedly an expensive widget. You can try measuring performance (not scientific because you would need a real phisical device):
main() async {
  testWidgets('test', (WidgetTester tester) async {
    final Stopwatch timer = new Stopwatch()..start();
    for (int index = 0; index < 1000; index += 1) {
      await tester.pumpWidget( MyApp());
    }
    timer.stop();
    debugPrint('Time taken: ${timer.elapsedMilliseconds}ms');
  });
}

Summary

It is unlikely that you need to match siblings widgets' height to a single one with an unknown height. If that is really the case, the widget must be first rendered and notified like this or indirectly with IntrinsicHeight.

EDIT

Option 6: If you know the width, you can use Stack.

Container(
        color: Colors.grey,
        child: Stack(
          children: <Widget>[
            Container(child: Text("T", style: TextStyle(fontSize: 90),),color: Colors.green, width: 200,),
            Positioned.fill(left: 100,child: Container(child: Text("TTTTT", style: TextStyle(fontSize: 20),),color: Colors.blue)),
          ],
        ),
      ),

Option 7: If you want to use ValueNotifier ValueListenableBuilder GlobalKey.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  GlobalKey _rowKey = GlobalKey();
  final ValueNotifier<double> _rowHeight = ValueNotifier<double>(-1);

  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance!.addPostFrameCallback(
        (_) => _rowHeight.value = _rowKey.currentContext!.size!.height);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        color: Colors.grey,
        child: ValueListenableBuilder<double>(
          valueListenable: _rowHeight,
          builder: (_, __, ___) => Row(
            key: _rowKey,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Container(
                child: Text(
                  "T",
                  style: TextStyle(fontSize: 90),
                ),
                color: Colors.green,
                width: 200,
              ),
              Container(
                  height: (_rowHeight.value<0)? null : _rowHeight.value,
                  child: Container(
                      child: Text(
                        "TTTTT",
                        style: TextStyle(fontSize: 20),
                      ),
                      color: Colors.blue)),
            ],
          ),
        ),
      ),
    );
  }
}

Upvotes: 6

R&#233;mi Rousselet
R&#233;mi Rousselet

Reputation: 277707

Sure ! Simply wrap your Row into an IntrinsicHeight

IntrinsicHeight(
  child: Row(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: <Widget>[],
  ),
);

Upvotes: 73

Related Questions