【问题标题】:How to make children of a Row have the same height by reading child constraints如何通过阅读孩子约束使一行的孩子具有相同的高度
【发布时间】:2021-11-27 02:41:35
【问题描述】:

我有一个带有代表的 SliverList,它为每个项目返回 Row。设计需要这个结果:

这两个孩子是Text和Image。 Image fir 是 BoxFit.cover,我使用 Flexible 为它们提供所需的宽度比。仅当高度大于或等于宽度边界时,我才需要图像边界高度来匹配文本高度(以使其至少保持一个正方形)。

第一个解决方案是使用 LayoutBuilder 读取图像宽度的约束,并将图像放在一个 ConstrainedBox 中,minHeight 为 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,
      ),
  ),
)

一切都很好,直到文本长于图像宽度,此时图像仍然是正方形并且不会拉伸到整个行高:

第二种解决方案是将 Row 包装在 IntrinsicHeight 小部件中。但这意味着我不能在其中使用 LayoutBuilder。所以我删除了布局构建器,现在我无法访问约束来设置图像 minHeight。图像很好地伸展以填充整个行高度。直到文本太短,导致图像高度低于其宽度:

如何构建此设计以响应可变文本高度?

【问题讨论】:

    标签: flutter dart flutter-layout constraints


    【解决方案1】:

    所以我选择了答案 1 并使其具有响应性和文本方向意识(针对 RTL 语言)。这是最终的解决方案:

    Stack(
      children: [
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Flexible(flex: 3, child: Text(("Hello There\n" * 10))),
            const Flexible(
              flex: 1,
              child: AspectRatio(
                aspectRatio: 1,
              ),
            )
          ],
        ),
        Positioned.fill(
          child: FractionallySizedBox(
            widthFactor: 0.25,
            alignment: AlignmentDirectional.topEnd,
            child: Image.network(
              'https://via.placeholder.com/600/92c952',
              fit: BoxFit.cover,
              // height: double.infinity,
            ),
          ),
        ),
      ],
    )
    

    【讨论】:

      【解决方案2】:

      这可以巧妙地使用Stack 来完成,因为Stack 的大小将匹配其未定位的子元素,因此它会自动匹配您的Text 小部件。然后使用Positioned 小部件显示图像 - 将其topbottom 设置为0 以使其垂直拉伸,设置right: 0 使其对齐,并为其提供固定宽度。

      示例源代码:

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

      更新:

      您在 cmets 中提到,您希望强制执行“最小高度”。您可以在Stack 中轻松做到这一点,方法是放置一个不可见的SizedBox,例如:

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

      结果:

      【讨论】:

      • 我已经实现了这一点(请参阅我的问题中的解决方案 2)。问题是将文本和图像的容器保持在当前图像宽度的最小高度,以便图像即使不高也至少是正方形(所需设计中的第一张图像)
      • @shadysamir 您的“解决方案 2”使用 IntrinsicHeight 这将导致布局两次,效率低下。要强制执行“最小高度”,您只需在 Stack 中添加另一个 SizedBox,请参阅我的更新答案。
      • 你把我送到了正确的方向。你的答案几乎就在那里。缺少的是响应能力。图像的可用宽度不一定是 100。我会写下我达到的答案,为我解决它。
      猜你喜欢
      • 2020-12-15
      • 2017-03-22
      • 1970-01-01
      • 2020-11-14
      • 1970-01-01
      • 2018-04-28
      • 2019-04-18
      • 1970-01-01
      • 2014-10-21
      相关资源
      最近更新 更多