Flutter RenderFlex在Column Widget内部右侧溢出了15个像素

时间:2018-10-16 10:47:57

标签: flutter

我创建了一个自定义ListTile,该列表应在中间居中放置两个分数,并在此(screenshot)的左侧和右侧提供信息。

左侧的信息可以具有任意长度,如果长度太长,则应使用TextOverflow.ellipsis。 由于文本似乎不知道它应该具有的宽度并且溢出,所以我无法使它起作用。 我尝试将文本小部件包装到SizedBox,Expanded等中。这没有用。

    flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
    flutter: The following message was thrown during layout:
    flutter: A RenderFlex overflowed by 15 pixels on the right.
    flutter:
    flutter: The overflowing RenderFlex has an orientation of Axis.horizontal.
    flutter: The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
    flutter: black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
    flutter: Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
    flutter: RenderFlex to fit within the available space instead of being sized to their natural size.
    flutter: This is considered an error condition because it indicates that there is content that cannot be
    flutter: seen. If the content is legitimately bigger than the available space, consider clipping it with a
    flutter: ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
    flutter: like a ListView.
    flutter: The specific RenderFlex in question is:
    flutter:   RenderFlex#c64e4 relayoutBoundary=up11 OVERFLOWING
    flutter:   creator: Row ← Expanded ← Row ← Column ← ConstrainedBox ← Container ← Listener ← _GestureSemantics
    flutter:   ← RawGestureDetector ← GestureDetector ← InkWell ← ScopedModelDescendant<BaseballModel> ← ⋯
    flutter:   parentData: offset=Offset(0.0, 0.0); flex=1; fit=FlexFit.tight (can use size)
    flutter:   constraints: BoxConstraints(w=143.0, 0.0<=h<=Infinity)
    flutter:   size: Size(143.0, 70.0)
    flutter:   direction: horizontal
    flutter:   mainAxisAlignment: start
    flutter:   mainAxisSize: max
    flutter:   crossAxisAlignment: center
    flutter:   textDirection: ltr
    flutter:   verticalDirection: down
    flutter: ◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤

我的代码如下:

@immutable
class GameTile extends StatelessWidget {
  final Game game;
  Color highligtColor = Colors.red;

  GameTile({this.game});

  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: Container(
        height: 70.0,
        child: Column(
          children: <Widget>[
            Row(
              children: <Widget>[
                Expanded(
                  child: Row(
                    children: <Widget>[
                      Container(
                        width: 8.0,
                        height: 70.0,
                        color: highligtColor,
                      ),
                      Padding(
                        padding: EdgeInsets.only(left: 15.0),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            Text(
                              game.awayTeam.name,
                              overflow: TextOverflow.ellipsis,
                            ),
                            Text(
                              game.homeTeam.name,
                              overflow: TextOverflow.ellipsis,
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.only(left: 8.0, right: 8.0),
                  child: Column(
                    children: [
                      Text(
                        game.awayRuns,
                        style: TextStyle(fontWeight: FontWeight.w900),
                      ),
                      Text(
                        game.homeRuns,
                        style: TextStyle(fontWeight: FontWeight.w900),
                      ),
                    ],
                  ),
                ),
                Expanded(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: <Widget>[
                      Column(
                          crossAxisAlignment: CrossAxisAlignment.end,
                          children: <Widget>[
                            Text(game.getFormattedDate()),
                            Text(game.getFormattedTime()),
                          ]),
                      Padding(
                        padding: EdgeInsets.only(left: 8.0, right: 10.0),
                        child: Container(),
                      )
                    ],
                  ),
                )
              ],
            )
          ],
        ),
      ),
    );
  }
}

5 个答案:

答案 0 :(得分:1)

关于例外情况

我在手机上运行了您的代码,只有在干涉了团队名称和小部件的宽度之后才发生异常。

我认为出现此问题是因为您的代码无法很好地适应不同的显示尺寸,尤其是在团队名称的长度不同的情况下:

both your widget and the modified version

针对更灵活,动态的小部件的具体解决方案

我创建了一个修改后的小部件,它可以很好地适应约束更改,并以更巧妙的方式使用可用空间。我通过尽可能扁平化嵌套的RowColumn来做到这一点,从而得到了一个更浅,更灵活的小部件树:

return InkWell(
  child: Container(
    height: 70.0,
    child: Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Container(width: 8.0, height: 70.0, color: highlightColor),
        SizedBox(width: 15.0),
        Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(game.awayTeam.name, overflow: TextOverflow.ellipsis),
            Text(game.homeTeam.name, overflow: TextOverflow.ellipsis),
          ],
        ),
        Spacer(),
        Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(game.awayRuns, style: TextStyle(fontWeight: FontWeight.w900)),
            Text(game.homeRuns, style: TextStyle(fontWeight: FontWeight.w900)),
          ],
        ),
        Spacer(),
        Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: <Widget>[
            Text(game.getFormattedDate()),
            Text(game.getFormattedTime()),
          ]
        ),
        SizedBox(width: 18.0),
      ],
    ),
  ),
);

处理困难约束时的一般提示

大多数时候,最好只在浅树中使用几个小部件。嵌套所有类型的“组织”窗口小部件,尤其是ColumnRowExpanded时,常常会导致Expanded总是要求相同大小(或父级尺寸),甚至不考虑其内容的尺寸。

这可能导致内容溢出,而小部件其他部分没有未使用的负空间。

答案 1 :(得分:1)

FlexibleExpanded 解决方案的说明

Row 内,Text 小部件在不在 ExpandedFlexible 小部件(或其他限制宽度的小部件)内时不会换行或显示省略号.

当 Flutter 为 RowColumn 执行布局时,任何非弹性因子小部件都会在无界空间中进行布局。即没有任何限制。 (FlexibleExpandedSpacer 是唯一的 flex-factor 小部件。)

因此,当 Text 被放置在 Row 内时,它永远不会宽到遇到宽度约束并被包裹,因为...

...对于非弹性因素,在Row布局期间没有约束小部件。


Text 小部件放置在 FlexibleExpanded 内将导致 Flutter 在 Row 布局期间计算剩余空间并施加该约束。如果需要,这将导致换行和省略号(如果指定):Text("blahblah", overflow: TextOverflow.ellipsis).

More details in a related RenderFlex overflowed question

示例代码

import 'package:flutter/material.dart';

class FlexTextWrapPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flex Text Wrap'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          SizedBox(
            width: 400,
            child: Row(
              children: [
                MySpacer(width: 100),
                Text("This should easily wrap, but doesn't because I'm in INFINITE SPACE"),
                MySpacer(width: 100),
              ],
            ),
          ),
          SizedBox(
            width: 400,
            child: Row(
              children: [
                MySpacer(width: 100),
                Expanded(child: Text("This should easily wrap, and DOES because I'm in BOUNDED SPACE")),
                MySpacer(width: 100),
              ],
            ),
          ),
          SizedBox(
            width: 400,
            child: Row(
              children: [
                MySpacer(width: 100),
                Expanded(
                    child: Text("This should easily wrap, and DOES because I'm in BOUNDED SPACE",
                      overflow: TextOverflow.ellipsis, // default is .clip
                      maxLines: 2,),// default is 1
                ),
                MySpacer(width: 100),
              ],
            ),
          ),

        ],
      ),
    );
  }
}

class MySpacer extends StatelessWidget {
  final double width;

  MySpacer({this.width});

  @override
  Widget build(BuildContext context) {
    return Container(child: SizedBox(width: width, height: 16,), color: Colors.lightBlueAccent,);
  }
}

结果

Overflow, Wrapping & Ellipses Text

答案 2 :(得分:0)

只需用Flexible包装溢出的小部件

new Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            new Checkbox(
              onChanged: (bool){},
            ),
            Flexible(
              child: new Text(
                "This text can be so loooooooooooooong",
              ),
            ),

          ],
        ),

答案 3 :(得分:0)

在父窗口小部件中使用ExpandedFlexible

答案 4 :(得分:0)

如果您希望子内容仅适合内容而不进行扩展。您必须在行内将FlexibleMainAxisSize.min结合使用:

Row(
  mainAxisAlignment: MainAxisAlignment.start,
  mainAxisSize: MainAxisSize.min,
  children: <Widget>[
    Flexible(
      child: Padding(
        padding: const EdgeInsets.only(right: 2),
        child: Text("abc",
          style: TextStyle(
              color: Colors.white,
              fontSize: 13),
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
        ),
      ),
    ),
    Icon(Icons.arrow_drop_down, size: 10, color: Colors.white,)
  ],
)

doanbh image