【问题标题】:Using FractionallySizedBox in a Row连续使用 FractionallySizedBox
【发布时间】:2019-07-28 16:04:09
【问题描述】:

我想要一个任意宽度的小部件,其中包含一行三个大小相对于其父级大小的小部件。

FractionallySizedBox 听起来是适合这项工作的工具,所以我这样尝试:

Container(height: 24.0, color: Colors.black, child:
  Row(children: [
    FractionallySizedBox(heightFactor: 1, widthFactor: 0.25,
                         child: Container(color: Colors.orange)),
    FractionallySizedBox(heightFactor: 1, widthFactor: 0.15,
                         child: Container(color: Colors.green)),
    FractionallySizedBox(heightFactor: 1, widthFactor: 0.05,
                         child: Container(color: Colors.blue)),
  ]
)

但我遇到了一个错误

BoxConstraints 强制使用无限宽度。

即使我在封闭容器上设置了一些宽度,也会发生这种情况。

为什么这不起作用?

【问题讨论】:

  • 您应该将此报告为错误,它应该能够在行或列中运行。
  • 这应该在 FractionallySizedBox 被包裹在 Flexible 中时起作用。报告了这个错误。 github.com/flutter/flutter/issues/44733

标签: flutter


【解决方案1】:

正如 Flutter 团队在“FractionallySizedBox (Flutter Widget of the Week)”视频中所解释的那样,FractionallySizedBox 需要被包裹在 Flexible 小部件中,“因此它可以很好地与行或列配合使用”。

参考:https://www.youtube.com/watch?v=PEsY654EGZ0

这应该是原始问题的解决方案,格式如下:

Container(
    height: 24.0, 
    color: Colors.black, 
    child: Row(
        children: [
            Flexible(
                child: FractionallySizedBox(
                    heightFactor: 1, widthFactor: 0.25,
                    child: Container(color: Colors.orange),
                ),
            ),
            Flexible(
                child: FractionallySizedBox(
                    heightFactor: 1, widthFactor: 0.15,
                    child: Container(color: Colors.green)),
            ),
            Flexible(
                child: FractionallySizedBox(
                    heightFactor: 1, widthFactor: 0.05,
                    child: Container(color: Colors.blue)
                ),
            ),
        ]
    )
)

我也做过类似的工作,正在寻找解决问题的方法,这是我表示数据级别的代码:

Row(
    children: <Widget>[
      Flexible(
        child: FractionallySizedBox(
            widthFactor: 1,
            child: Container(
              margin: EdgeInsets.only(right: 5),
              height: 6,
              decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.all(Radius.circular(125)),
              ),
            )
        ),
      ),
      Flexible(
        child: FractionallySizedBox(
            widthFactor: 1,
            child: Container(
              margin: EdgeInsets.only(right: 5),
              height: 6,
              decoration: BoxDecoration(
                color: Colors.blue,
                borderRadius: BorderRadius.all(Radius.circular(125)),
              ),
            )
        ),
      ),
      Flexible(
        child: FractionallySizedBox(
            widthFactor: 1,
            child: Container(
              margin: EdgeInsets.only(right: 5),
              height: 6,
              decoration: BoxDecoration(
                color: Colors.blue,
                borderRadius: BorderRadius.all(Radius.circular(125)),
              ),
            )
        ),
      ),
      Flexible(
        child: FractionallySizedBox(
            widthFactor: 1,
            child: Container(
              margin: EdgeInsets.only(right: 5),
              height: 6,
              decoration: BoxDecoration(
                color: Colors.blue,
                borderRadius: BorderRadius.all(Radius.circular(125)),
              ),
            )
        ),
      ),
      Flexible(
        child: FractionallySizedBox(
            widthFactor: 1,
            child: Container(
              margin: EdgeInsets.only(right: 5),
              height: 6,
              decoration: BoxDecoration(
                color: Colors.blue,
                borderRadius: BorderRadius.all(Radius.circular(125)),
              ),
            )
        ),
      ),
    ],
),

导致: evenly spaced bars

【讨论】:

    【解决方案2】:

    您不能直接在行或列中使用FractionallySizedBox。您可以使用 Expand 小部件的 flex 参数拆分为百分比 Row 和 Column,如下所示。

    Row(
          children: <Widget>[
            Expanded(
              flex: 6, // 60% of space => (6/(6 + 4))
              child: Container(
                color: Colors.red,
              ),
            ),
            Expanded(
              flex: 4, // 40% of space
              child: Container(
                color: Colors.purple,
              ),
            ),
          ],
        ),
    

    【讨论】:

    • 为什么他们会说它在 45 秒左右的行或列中表现良好:youtube.com/…
    • @SoufianeGhzal 您可以用 Expanded 或 Flexible 小部件包装 FractionallySizedBox,不能直接使用。他们已经在视频中用 Flexible 包装了它。
    • 是的,我只是觉得它令人困惑,因为他们说的方式你认为可以直接使用它来调整行或列的大小。至少我一开始是这么理解的。
    【解决方案3】:

    FractionallySizedBox 似乎只能在 Row、Column 和 Wrap 小部件之外工作。我会推荐这种方法:

    class FractionalPositioningQuestion extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
    
        // Replace with the size your parent widget is.
        final pWidth = MediaQuery.of(context).size.width;
    
        return Row(children: <Widget>[
          Container(
            width: pWidth * 0.25,
            color: Colors.orange,
          ),
          Container(
            width: pWidth * 0.15,
            color: Colors.green,
          ),
          Container(
            width: pWidth * 0.05,
            color: Colors.blue,
          ),
        ],
        mainAxisAlignment: MainAxisAlignment.center, // Depending on what you want
        );
      }
    }
    

    您仍然需要找到一种方法来获取父窗口小部件的任意宽度。

    希望这至少会有所帮助:-)

    【讨论】:

    • 不幸的是,这仅在您的行占用显示的整个宽度时才有效。如果你在行周围有填充,行是一个组件,你会很难过。
    【解决方案4】:

    FractionallySizedBox 拒绝在 Rows 中工作。 使用 Expanded 的 flex 字段更容易。

    import 'package:flutter/material.dart';
    
    myRow() => Row(children: [
          Expanded(
            flex: 8,
            child: Container(
              height: 100,
              color: Colors.green,
            ),
          ),
          Expanded(
            flex: 2,
            child: Container(
              height: 100,
              color: Colors.red,
            ),
          ),
        ]);
    
    content() => Column(children: [
          Text(" ----Start ----"),
          myRow(),
          Text(" ----End ----"),
        ]);
    
    void main() => runApp(MyApp());
    
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) => MaterialApp(
          title: 'Flutter Playground',
          home: Material(
              child: SafeArea(child: Container(width: 80, child: content()))));
    }
    

    【讨论】:

      【解决方案5】:

      FractionallySizedBox 在行和列中无法按预期工作,甚至包装在灵活的小部件中。

      tldr:似乎 heightFactor(用于列)不是应用于框本身,而是应用于整个列。这是一个简洁的效果,但不是预期的效果

      详情:

      我制作了一个DartPad,让你看到它。

      • OrangeBox 的 heighFactor=0.5(您可以在代码中更改)
      • 蓝框固定为 20 x 20 像素。

      问题1

      预期行为:两个 OrangeBox 占据了整个屏幕。各半。 实际行为:两个 OrangeBox 各占 1/4。

      问题2

      预期行为:一个 OrangeBox 占据了屏幕的一半。添加 BlueBoxes 不会使 Orange Box 变小。 实际行为:添加 BlueBoxes 会使 OrangeBox 更小。这样整列就占据了屏幕的一半。然后,如果添加许多蓝框,则整个列最终会增长。

      照片

      我还在 Android 上对此进行了测试,通过快速检查得到了相同的渲染行为。

      补充说明

      如果有一天 dartpad 链接断开,要点就在这里 https://gist.github.com/chonghorizons/0d97a4202a0cd8838aa25713f1c19c13

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-30
        • 2021-08-31
        • 1970-01-01
        • 2018-07-23
        • 2015-08-19
        相关资源
        最近更新 更多