在Flutter中的相当于wrap_content和match_parent的属性是什么?

278

在Android中,match_parentwrap_content被用于根据widget包含的内容相对于其父级自动调整widget的大小。

在Flutter中,默认情况下所有的widget都被设置为wrap_content,那么我该如何改变它,以便使其填充到其父级的widthheight

14个回答

465
请注意:父部件的默认行为是使用其子部件填充所有可用空间。Scaffold > body > Container(sized)与 Scaffold > body > Center > Container(sized)不同。
您可以在https://docs.flutter.dev/ui/layout/constraints中阅读更多信息。
理解这一点将清楚您如何工作的概念:约束向下,尺寸增大,父级设置位置。 您可以使用一点技巧来实现: 假设您有以下要求: (宽度,高度) Wrap_content, Wrap_content:
 //use this as child
 Wrap(
  children: <Widget>[*your_child*])

Match_parent,Match_parent:

 //use this as child
Container(
        height: double.infinity,
    width: double.infinity,child:*your_child*)

Match_parent,Wrap_content :

 //use this as child
Row(
  mainAxisSize: MainAxisSize.max,
  children: <Widget>[*your_child*],
);

Wrap_content ,Match_parent:

 //use this as child
Column(
  mainAxisSize: MainAxisSize.max,
  children: <Widget>[your_child],
);

6
为了匹配父级,您还可以使用SizedBox.expand()来包装您的小部件。 - Wecherowski
1
我同意所有的情况,除了一个。Wrap_content, Wrap_content这种情况由Flutter设计处理(这很棒,你不需要每次都分配宽度和高度)。Wrap有不同的用法,在这里解释:https://www.youtube.com/watch?v=z5iw2SeFx2M - PrzemekTom

263
为了使match_parentwrap_content生效,我们需要在Row/Column小部件中使用mainAxisSize属性,该属性采用具有两个值的MainAxisSize枚举,即MainAxisSize.min,它的行为类似于wrap_content,以及MainAxisSize.max,它的行为类似于match_parent

enter image description here

原文章链接


19
RowsColumns中还有一个名为crossAxisAlignment的属性,可以将其设置为CrossAxisAlignment.stretch,以便在Column中水平展开。 - wamfous
很棒的答案!如果有人正在寻找更多类似的示例,请使用以下链接 https://medium.com/flutter-community/flutter-layout-cheat-sheet-5363348d037e - Swapnil Kadam

46

简而言之,父级在子级确定大小之前没有大小。

在Flutter中,布局的工作方式是每个widget为其每个子widget提供约束,例如“您可以多宽,必须这么高,必须至少这么宽”等等(具体来说,它们获得最小宽度、最大宽度、最小高度和最大高度)。每个子widget获取这些约束,执行某些操作,并选择与这些约束匹配的大小(宽度和高度)。然后,一旦每个子widget都完成了自己的任务,父级widget可以选择自己的大小。

有些widget尝试尽可能大,以适应父级大小。有些widget尝试尽可能小,以适应父级大小。有些widget尝试匹配特定的“自然”大小(例如文本、图像)。

有些widget告诉它们的子widget它们可以任意大小。有些widget将相同的约束传递给它们从父widget获取的子widget。


2
当我在Column里面有一个PageView,并且当前页面内又有另一个Column时,我会收到渲染错误的提示。但是我可以通过将PageView包装在ExpandedFlexible中来解决它。问题是,这两个选项只会扩展它们的子级。为什么没有与之相关的小部件来缩小适配,比如“包装内容”,以解决此类渲染问题呢? - Michel Feinstein
这种行为类似于Android Jetpack Compose UI工具包。 - MJ Studio

32

实际上有几种选择:

你可以使用SizedBox.expand使你的小部件与父部件尺寸匹配,或者使用SizedBox(width: double.infinity)仅匹配宽度或SizedBox(height: double.infinity)仅匹配高度。

如果你想要wrap_content行为,这取决于您使用的父小部件,例如如果您将按钮放在列上,则它将像wrap_content一样运作,而要像match_parent一样使用它,您可以使用Expanded小部件或SizedBox包装按钮。

对于ListView,按钮具有match_parent行为,要获取wrap_content行为,您可以使用Flex小部件(如Row)包装它。

使用Expanded小部件使得Row、Column或Flex的子项展开以填充主轴上的可用空间(例如,在Row上是水平方向,在Column上是垂直方向)。 https://docs.flutter.io/flutter/widgets/Expanded-class.html

使用Flexible小部件为Row、Column或Flex的子项提供了灵活性,使其能够扩展以填充主轴上的可用空间(例如,在Row上是水平方向,在Column上是垂直方向),但与Expanded不同,Flexible不要求子项填充可用空间。 https://docs.flutter.io/flutter/widgets/Flexible-class.html


24
使用小部件 Wrap。对于类似于Column的行为,请尝试:
  return Wrap(
          direction: Axis.vertical,
          spacing: 10,
          children: <Widget>[...],);

尝试以下代码以实现类似于Row的行为:

  return Wrap(
          direction: Axis.horizontal,
          spacing: 10,
          children: <Widget>[...],);

更多信息请参考:Wrap (Flutter Widget)


15

要让一个子元素填充其父元素,只需将其包裹在FittedBox中即可。

    FittedBox(
     child: Image.asset('foo.png'),
     fit: BoxFit.fill,
   )

14

我使用了这个解决方案,你需要使用MediaQuery定义屏幕的高度和宽度:

 Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width
  )

1
如果内容高度超过屏幕高度,这个解决方案会出现严重的问题,会抛出溢出异常。 - jokermt235

10

一个简单的解决方法:

如果容器只有一个顶级子元素,则可以为该子元素指定对齐属性并赋予任何可用值。它将填充容器中所有的空间。

Container(color:Colors.white,height:200.0,width:200.0,
 child:Container(
    color: Colors.yellow,
    alignment:Alignment.[any_available_option] // make the yellow child match the parent size
   )
)

另外一种方法:

Container(color:Colors.white,height:200.0,width:200.0,
 child:Container(
    color: Colors.yellow,
    constraints:  BoxConstraints.expand(height: 100.0), // height will be 100 dip and width will be match parent
   )
)

BoxConstraints.expand(height: 100.0) 作为Android中 width="match_parent" 的等价物非常好用。 - kosiara - Bartosz Kosarzycki

10
Stack(
  children: [
    Container(color:Colors.red, height:200.0, width:200.0),
    Positioned.fill(
      child: Container(color: Colors. yellow),
    )
  ]
),

1
虽然您的代码可能回答了问题,但好的答案应该总是解释代码的作用以及如何解决问题。 - BDL
1
这是与包装内容不同的硬编码宽度和高度。 - Developine

8
使用 FractionallySizedBox 小部件。
FractionallySizedBox(
  widthFactor: 1.0, // width w.r.t to parent
  heightFactor: 1.0,  // height w.r.t to parent
  child: *Your Child Here*
}

当您想让子元素的大小为父元素大小的一部分时,此小部件也非常有用。

例如:

如果您想让子元素占其父元素宽度的50%,请将widthFactor设置为0.5


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