Flutter 布局 Row / Column - 宽度共享,高度扩展

119
我在Flutter中的布局仍然有一些困难。 现在,我想要三个widget共享可用空间,在四分之一布局中。 宽度均匀共享(通过Row中的2个Expanded widget可以正常工作),但是现在我还希望高度自动调整,使得widget3.height == widget1.height + widget2.heightlayout 如果widget3的内容更大,则希望widget1widget2调整其高度,反之亦然。 Flutter是否支持这种布局方式?
5个回答

365

看一下IntrinsicHeight;将根Row包装起来应该会提供您正在寻找的效果:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(title: Text('Rows & Columns')),
        body: RowsAndColumns(),
      ),
    );
  }
}

class RowsAndColumns extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 100.0),
      child: IntrinsicHeight(
        child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
          Expanded(
            child: Column(children: [
              Container(height: 120.0, color: Colors.yellow),
              Container(height: 100.0, color: Colors.cyan),
            ]),
          ),
          Expanded(child: Container(color: Colors.amber)),
        ]),
      ),
    );
  }
}

调整列中容器的高度会导致右侧的容器调整大小以匹配:

screenshot

https://gist.github.com/mjohnsullivan/c5b661d7b3b4ca00599e8ef87ff6ac61


20
太棒了,以前从未听说过"IntrinsicHeight"! - TommyF
12
你确定没有其他方法可以做到这一点吗? 因为在官方文档中,它指出不要使用这个小部件,因为它太昂贵了。 - Gurleen Sethi
37
Flutter文档中有一条关于IntrinsicHeight的注释:这个类相对来说比较昂贵。尽量避免在可能的情况下使用它。 - stevenspiel
5
虽然价格较高,但我认为Flutter没有其他更好、更快的替代方案。 - Giraldi
4
可以在列表中使用吗?@matt-s - Sp4Rx
显示剩余9条评论

10
自从IntrinsicHeight被认为是相对昂贵的,最好避免使用它。您可以在最大的TableCell中使用verticalAlignment: TableCellVerticalAlignment.fillTable
请注意,如果您在所有单元格中都使用了.fill,那么TableRow将具有零高度
  Table(children: [
    TableRow(children: [
      Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Container(
            alignment: Alignment.center,
            color: Colors.blue,
            child: Text('Widget 1'),
          ),
          Container(
            alignment: Alignment.center,
            color: Colors.green,
            child: Text('Widget 2'),
          ),
        ],
      ),
      TableCell(
          verticalAlignment: TableCellVerticalAlignment.fill,
          child: Container(
            alignment: Alignment.center,
            color: Colors.orange,
            child: Text('Widget 3'),
          )),
    ]),
  ]),

9

我认为您可以设置行的高度,然后只需要设置列容器的高度,使用 crossAxisAlignment: CrossAxisAlignment.stretch,第二行将会扩展并占用其父容器的高度:

Row(
  crossAxisAlignment: CrossAxisAlignment.stretch,
  children: [
    Expanded(
      child: Column(
        children: [
          Expanded(
            // If you don't have the height you can expanded with flex
            flex: 1,
            child: Container(
              height: 50,
              color: Colors.blue,
            ),
          ),
          Expanded(
            flex: 1,
            child: Container(
              height: 50,
              color: Colors.red,
            ),
          )
        ],
      ),
    ),
    Expanded(
      child: Container(
        color: Colors.yellow,
      ),
    )
  ],
)

2
这个解决方案很整洁,我有点喜欢它。 - Godwin Mathias
在我的情况下不起作用。我得到了BoxConstraints forces an infinite height.错误。 - undefined

1

我刚开始接触flutter,如果我做错了什么,请纠正我。我认为使用setState((){})也可以实现这一点,而不必使用IntrinsicHeight。

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    double h1 = 100;
    double h2 = 200;
    double h3;
    setState(() {
      h3 = h1 + h2;
    });
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: Padding(
            padding: const EdgeInsets.only(top: 100.0),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Expanded(
                  child: Column(
                    children: [
                      Container(
                        color: Colors.green,
                        height: h1,
                      ),
                      Container(
                        color: Colors.orange,
                        height: h2,
                      )
                    ],
                  ),
                ),
                Expanded(
                  child: Container(
                    color: Colors.yellow,
                    height: h3,
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

点击此处查看图片

此代码也可在此处找到:https://gist.github.com/Amrit0786/9d228017c2df6cf277fbbaa4a6b20e83


4
如果你有一个庞大的应用程序,你会希望尽可能地减少 StatefulWidget 的使用。相反地,可以使用内置解决方案的 StatelessWidget。在布局中使用 Stateful 不是技术上的错误,但除非没有其他选择,否则不应使用它。 - Smily
我正在努力理解为什么你在build方法中使用setState?!!哇……! - youssef ali

-1
如果您已经在使用Row和Expanded来解决高度问题,那么只需将Expanded子元素包装在Align小部件中即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接