Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 337
Chris Avatar asked Jun 18 '18 17:06

Chris


Video Answer


2 Answers

Sure ! Simply wrap your Row into an IntrinsicHeight

IntrinsicHeight(
  child: Row(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: <Widget>[],
  ),
);
like image 64
Rémi Rousselet Avatar answered Jan 14 '23 05:01

Rémi Rousselet


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)),
            ],
          ),
        ),
      ),
    );
  }
}

like image 39
Roddy R Avatar answered Jan 14 '23 05:01

Roddy R