flutter 为什么列占其父列(容器)的全宽

envsm3lx  于 2023-03-09  发布在  Flutter
关注(0)|答案(3)|浏览(184)

1.我在一个容器里放了一根柱子
1.容器的宽度设置为300
1.该列具有文本子级
1.一般来说,列宽是它最宽的子元素的宽度,在这个例子中,它只有一个文本子元素,所以列宽应该是文本子元素的宽度
1.但是,该列将扩展到父代的全宽300,即宽度为300的容器父代

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Padding(
          padding: EdgeInsets.all(10),
          child: Container(
            width: 300,
            color: Colors.orangeAccent,
            child: Column(
              // mainAxisSize: MainAxisSize.min,
              children: [
                Text('Hi', style: TextStyle(fontSize: 50)),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

1.我们可以观察到列扩展到父列的全宽,这是通过在图像中看到子列居中对齐(默认的横轴对齐)来实现的。

我浏览了容器文档,但无法弄清楚为什么会发生这种情况。有人能解释一下为什么该列会占据其父列的全宽吗?

8cdiaqws

8cdiaqws1#

列将采用Container的全宽,因为Container强制它这样做。如果您指定Container的宽度,则Container基本上将使用ConstrainedBox,并对其子级进行严格约束。在您的情况下,顺序为minWidth = 300
如果你想让Column尽可能的窄,你应该用UnconstrainedBox小部件 Package 它,这将把Container的严格约束用于它自己,并使Column具有它的“自然”大小。如果你仍然想让Column尽可能的高,你需要指定constrainedAxis:无约束框的轴垂直属性

30byixjq

30byixjq2#

为了更好地理解Container是如何工作的,这里是小部件的实现,您可以在flutter源代码中找到:

Container({
  Key? key,
  this.alignment,
  this.padding,
  this.color,
  this.decoration,
  this.foregroundDecoration,
  double? width,
  double? height,
  BoxConstraints? constraints,
  this.margin,
  this.transform,
  this.transformAlignment,
  this.child,
  this.clipBehavior = Clip.none,
}) : assert(margin == null || margin.isNonNegative),
       assert(padding == null || padding.isNonNegative),
       assert(decoration == null || decoration.debugAssertIsValid()),
       assert(constraints == null || constraints.debugAssertIsValid()),
       assert(clipBehavior != null),
       assert(decoration != null || clipBehavior == Clip.none),
       assert(color == null || decoration == null,
         'Cannot provide both a color and a decoration\n'
         'To provide both, use "decoration: BoxDecoration(color: color)".',
       ),
       constraints =
        (width != null || height != null)
          ? constraints?.tighten(width: width, height: height)
            ?? BoxConstraints.tightFor(width: width, height: height)
          : constraints,
       super(key: key);

有趣的是constraints属性:

constraints =
  (width != null || height != null)
    ? constraints?.tighten(width: width, height: height)
      ?? BoxConstraints.tightFor(width: width, height: height)
    : constraints

正如您所看到的,如果您为width和/或height属性给予,它会将BoxConstraints应用于其子小部件,强制您的子小部件Column遵守此约束。

更新:alignment属性如何工作?

如果您查看Container小部件的源代码,您会在其build方法中发现这一点。

Widget build(BuildContext context) {
  Widget? current = child;

  // ...

  if (alignment != null)
    current = Align(alignment: alignment!, child: current);

  // ...
}

这意味着通过提供一个非空的alignment属性,child小部件将被 Package 在一个Align小部件中,现在让我们来看看Align小部件的实现,更准确地说是它的createRenderObject()方法:

@override
RenderPositionedBox createRenderObject(BuildContext context) {
  return RenderPositionedBox(
    alignment: alignment,
    widthFactor: widthFactor,
    heightFactor: heightFactor,
    textDirection: Directionality.maybeOf(context),
  );
}

因此,通过提供Align小部件,它将创建一个RenderPositionedBox,让我们通过方法performLayout()来看看它的实现:

@override
void performLayout() {
  final BoxConstraints constraints = this.constraints;
  final bool shrinkWrapWidth = _widthFactor != null || constraints.maxWidth == double.infinity;
  final bool shrinkWrapHeight = _heightFactor != null || constraints.maxHeight == double.infinity;

  if (child != null) {
    child!.layout(constraints.loosen(), parentUsesSize: true);
    size = constraints.constrain(Size(
      shrinkWrapWidth ? child!.size.width * (_widthFactor ?? 1.0) : double.infinity,
      shrinkWrapHeight ? child!.size.height * (_heightFactor ?? 1.0) : double.infinity,
    ));
    alignChild();
  } else {
    size = constraints.constrain(Size(
      shrinkWrapWidth ? 0.0 : double.infinity,
      shrinkWrapHeight ? 0.0 : double.infinity,
    ));
  }
}

这样,您就可以根据其父级的maxWidthmaxHeight将一些BoxConstraints应用于您的child

643ylb08

643ylb083#

尝试设置mainAxisSize,但是给父容器一个alignment。如果子容器比父容器小,并且没有对齐,容器不知道在哪里绘制子容器,所以它会强制它采用全尺寸:

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Padding(
          padding: EdgeInsets.all(10),
          child: Container(
            width: 300,
            color: Colors.orangeAccent,
            alignment: Alignment.center,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text('Hi', style: TextStyle(fontSize: 50)),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

相关问题