相当于 wrap_content 和 match_parent 在 flutter 中的作用?
The equivalent of wrap_content and match_parent in flutter?
在 Android 中,match_parent
和 wrap_content
用于相对于其父级自动调整小部件的大小以适应小部件包含的内容。
在 Flutter 中,默认情况下所有小部件似乎都设置为 wrap_content
,我该如何更改它以便我可以将其 width
和 height
填充为其父级?
简短的回答是 parent 没有尺寸,直到 child 有尺寸。
布局在 Flutter 中的工作方式是每个小部件为其每个 children 提供约束,例如 "you can be up to this wide, you must be this tall, you have to be at least this wide" 或其他任何内容(具体来说,它们具有最小宽度、最大宽度、最小高度和最大高度)。每个 child 接受这些约束,做一些事情,然后选择与这些约束相匹配的大小(宽度和高度)。然后,一旦每个 child 都完成了它的工作,小部件就可以选择自己的大小。
一些小部件试图尽可能大 parent 允许。一些小部件试图尽可能小 parent 允许。一些小部件尝试匹配特定的 "natural" 大小(例如文本、图像)。
一些小部件告诉他们 children 他们可以是他们想要的任何大小。有些人给他们的 children 和他们 parent.
一样的限制
实际上有一些可用的选项:
您可以使用 SizedBox.expand 使您的小部件匹配 parent 的尺寸,或 SizedBox(width: double.infinity) 仅匹配宽度或 SizedBox(heigth: double.infinity) 以仅匹配高度。
如果您想要 wrap_content 行为,它取决于您使用的 parent 小部件,例如,如果您在列上放置一个按钮,它的行为将类似于 wrap_content 并且像 match_parent 一样使用它,您可以用扩展小部件或大小框包装按钮。
使用 ListView,按钮会获得 match_parent 行为,要获得 wrap_content 行为,您可以使用 Row 等 Flex 小部件将其包装起来。
使用 Expanded 小部件可以 child 行、列或 Flex
扩展以填充主轴中可用的 space(例如,水平
行或垂直列)。
https://docs.flutter.io/flutter/widgets/Expanded-class.html
使用灵活的小部件使行、列或 Flex 的 child 可以灵活扩展以填充主轴中可用的 space(例如,行的水平或垂直对于列),但是与扩展不同,灵活不需要 child 来填充可用的 space。
https://docs.flutter.io/flutter/widgets/Flexible-class.html
一个简单的解决方法:
如果一个容器只有一个顶级子项,那么您可以为子项指定对齐方式 属性 并为其赋予任何可用值。它将填满容器中的所有 space。
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
)
)
In order to get behavior for match_parent and wrap_content we need to
use mainAxisSize property in Row/Column widget, the mainAxisSize
property takes MainAxisSize enum having two values which is
MainAxisSize.min which behaves as wrap_content and MainAxisSize.max
which behaves as match_parent.
原文章
在专栏中使用这行代码。
对于 wrap_content :mainAxisSize: MainAxisSize.min
对于 match_parent :mainAxisSize: MainAxisSize.max
你可以用小技巧来做:
假设您有以下要求:
(宽度,高度)
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],
);
Stack(
children: [
Container(color:Colors.red, height:200.0, width:200.0),
Positioned.fill(
child: Container(color: Colors. yellow),
)
]
),
我使用了这个解决方案,你必须使用 MediaQuery 定义屏幕的高度和宽度:
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width
)
使用小工具 Wrap
。
对于Column
喜欢的行为尝试:
return Wrap(
direction: Axis.vertical,
spacing: 10,
children: <Widget>[...],);
对于Row
喜欢的行为尝试:
return Wrap(
direction: Axis.horizontal,
spacing: 10,
children: <Widget>[...],);
使用 FractionallySizedBox
小部件。
FractionallySizedBox(
widthFactor: 1.0, // width w.r.t to parent
heightFactor: 1.0, // height w.r.t to parent
child: *Your Child Here*
}
当您想将 child 的尺寸缩小为 parent 尺寸的一小部分时,此小部件也非常有用。
Example:
If you want the child to occupy 50% width of its parent, provide widthFactor
as 0.5
要让子项填充其父项,只需将其包装到 FittedBox 中即可
FittedBox(
child: Image.asset('foo.png'),
fit: BoxFit.fill,
)
匹配Parent
要匹配或填充 parent(高度和宽度),我们可以在 Container
上使用额外的 constraints
:
Container(
constraints: BoxConstraints.expand(), // ← this guy
child: Text('Center > Container > Text')
)
在 Flutter 中,constraints
是您可以填充的 space(或者 必须 填充,如果“紧”约束)。
约束是给定的...实际上没有,强加 parents.
默认情况下,Container
将包装其内容 (child:
) 并将其自身调整为 child,除非被覆盖(或严格限制不允许)。
使用 constraints:
参数,我们可以给 Container
额外的 约束来覆盖默认的 Container
约束行为(例如包装内容) .
使用Container(constraints: BoxConstraints.something)
不会覆盖incoming/parent约束;它只允许我们在允许的情况下覆盖默认行为,例如包装内容。
代码示例 - BoxConstraints
这是一个 copy/paste 代码示例,显示了各种 constraints
的效果,我们可以将其应用于具有“松散” incoming/parent 约束的 Container
(由 Center
).
import 'package:flutter/material.dart';
class MatchParentPage extends StatefulWidget {
@override
_MatchParentPageState createState() => _MatchParentPageState();
}
class _MatchParentPageState extends State<MatchParentPage> {
BoxConstraints constraints;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Match Parent'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded( // shares space constraint evenly with other Expanded
child: Center( // ← fills tight parent constraint & loosens ↓ child constraint ↓
child: Container( // got loose constraint from Center...
constraints: constraints, // can apply many additional constraints
color: Colors.lightBlueAccent.withOpacity(.3),
child: Text('Center > Container > Text')),
),
),
Expanded(
child: Container(
color: Colors.orangeAccent,
child: Wrap(
children: [
_button('default', null),
_button('*expand()', BoxConstraints.expand()),
_button('*tight(Size.infinite)', BoxConstraints.tight(Size.infinite)),
_button('tight(Size.zero)', BoxConstraints.tight(Size.zero)),
_button('tight(Size.fromHeight(100))', BoxConstraints.tight(Size.fromHeight(100))),
_button('tight(Size.fromWidth(100))', BoxConstraints.tight(Size.fromWidth(100))),
_button('tightForFinite(width: 100, height: 100)', BoxConstraints.tightForFinite(width: 100, height: 100)),
_button('loose(Size.infinite)', BoxConstraints.loose(Size.infinite)),
_button('tightFor(width: double.infinity)', BoxConstraints.tightFor(width: double.infinity)),
_button('tightFor(height: double.infinity)', BoxConstraints.tightFor(height: double.infinity)),
])
),
)
],
),
);
}
Widget _button(String label, BoxConstraints _constraints) {
bool _active = _constraints == constraints;
return Padding(
padding: const EdgeInsets.only(top:8, left: 8),
child: RaisedButton(
color: _active ? Colors.cyanAccent : null,
child: Text(label),
onPressed: () {
setState(() => constraints = _constraints);
},
),
);
}
}
MATCH_PARENT
FractionallySizedBox(
widthFactor: 1.0, // width w.r.t to parent
heightFactor: 1.0, // height w.r.t to parent
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
或
Container(
height: double.infinity,
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
或
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
或
Container(
constraints: BoxConstraints.expand(),
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
WRAP_CONTENT
Wrap(children: [
Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
])
或
Container(
constraints: BoxConstraints.tightFor(),
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
Match_parent,Wrap_content :
Row(
children: [
Expanded(
child: Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
),
])
Wrap_content,Match_parent :
Column(
children: [
Expanded(
child: Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
),
])
在 Android 中,match_parent
和 wrap_content
用于相对于其父级自动调整小部件的大小以适应小部件包含的内容。
在 Flutter 中,默认情况下所有小部件似乎都设置为 wrap_content
,我该如何更改它以便我可以将其 width
和 height
填充为其父级?
简短的回答是 parent 没有尺寸,直到 child 有尺寸。
布局在 Flutter 中的工作方式是每个小部件为其每个 children 提供约束,例如 "you can be up to this wide, you must be this tall, you have to be at least this wide" 或其他任何内容(具体来说,它们具有最小宽度、最大宽度、最小高度和最大高度)。每个 child 接受这些约束,做一些事情,然后选择与这些约束相匹配的大小(宽度和高度)。然后,一旦每个 child 都完成了它的工作,小部件就可以选择自己的大小。
一些小部件试图尽可能大 parent 允许。一些小部件试图尽可能小 parent 允许。一些小部件尝试匹配特定的 "natural" 大小(例如文本、图像)。
一些小部件告诉他们 children 他们可以是他们想要的任何大小。有些人给他们的 children 和他们 parent.
一样的限制实际上有一些可用的选项:
您可以使用 SizedBox.expand 使您的小部件匹配 parent 的尺寸,或 SizedBox(width: double.infinity) 仅匹配宽度或 SizedBox(heigth: double.infinity) 以仅匹配高度。
如果您想要 wrap_content 行为,它取决于您使用的 parent 小部件,例如,如果您在列上放置一个按钮,它的行为将类似于 wrap_content 并且像 match_parent 一样使用它,您可以用扩展小部件或大小框包装按钮。
使用 ListView,按钮会获得 match_parent 行为,要获得 wrap_content 行为,您可以使用 Row 等 Flex 小部件将其包装起来。
使用 Expanded 小部件可以 child 行、列或 Flex 扩展以填充主轴中可用的 space(例如,水平 行或垂直列)。 https://docs.flutter.io/flutter/widgets/Expanded-class.html
使用灵活的小部件使行、列或 Flex 的 child 可以灵活扩展以填充主轴中可用的 space(例如,行的水平或垂直对于列),但是与扩展不同,灵活不需要 child 来填充可用的 space。 https://docs.flutter.io/flutter/widgets/Flexible-class.html
一个简单的解决方法:
如果一个容器只有一个顶级子项,那么您可以为子项指定对齐方式 属性 并为其赋予任何可用值。它将填满容器中的所有 space。
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
)
)
In order to get behavior for match_parent and wrap_content we need to use mainAxisSize property in Row/Column widget, the mainAxisSize property takes MainAxisSize enum having two values which is MainAxisSize.min which behaves as wrap_content and MainAxisSize.max which behaves as match_parent.
在专栏中使用这行代码。
对于 wrap_content :mainAxisSize: MainAxisSize.min
对于 match_parent :mainAxisSize: MainAxisSize.max
你可以用小技巧来做: 假设您有以下要求: (宽度,高度)
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],
);
Stack(
children: [
Container(color:Colors.red, height:200.0, width:200.0),
Positioned.fill(
child: Container(color: Colors. yellow),
)
]
),
我使用了这个解决方案,你必须使用 MediaQuery 定义屏幕的高度和宽度:
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width
)
使用小工具 Wrap
。
对于Column
喜欢的行为尝试:
return Wrap(
direction: Axis.vertical,
spacing: 10,
children: <Widget>[...],);
对于Row
喜欢的行为尝试:
return Wrap(
direction: Axis.horizontal,
spacing: 10,
children: <Widget>[...],);
使用 FractionallySizedBox
小部件。
FractionallySizedBox(
widthFactor: 1.0, // width w.r.t to parent
heightFactor: 1.0, // height w.r.t to parent
child: *Your Child Here*
}
当您想将 child 的尺寸缩小为 parent 尺寸的一小部分时,此小部件也非常有用。
Example:
If you want the child to occupy 50% width of its parent, provide
widthFactor
as0.5
要让子项填充其父项,只需将其包装到 FittedBox 中即可
FittedBox(
child: Image.asset('foo.png'),
fit: BoxFit.fill,
)
匹配Parent
要匹配或填充 parent(高度和宽度),我们可以在 Container
上使用额外的 constraints
:
Container(
constraints: BoxConstraints.expand(), // ← this guy
child: Text('Center > Container > Text')
)
在 Flutter 中,constraints
是您可以填充的 space(或者 必须 填充,如果“紧”约束)。
约束是给定的...实际上没有,强加 parents.
默认情况下,Container
将包装其内容 (child:
) 并将其自身调整为 child,除非被覆盖(或严格限制不允许)。
使用 constraints:
参数,我们可以给 Container
额外的 约束来覆盖默认的 Container
约束行为(例如包装内容) .
使用Container(constraints: BoxConstraints.something)
不会覆盖incoming/parent约束;它只允许我们在允许的情况下覆盖默认行为,例如包装内容。
代码示例 - BoxConstraints
这是一个 copy/paste 代码示例,显示了各种 constraints
的效果,我们可以将其应用于具有“松散” incoming/parent 约束的 Container
(由 Center
).
import 'package:flutter/material.dart';
class MatchParentPage extends StatefulWidget {
@override
_MatchParentPageState createState() => _MatchParentPageState();
}
class _MatchParentPageState extends State<MatchParentPage> {
BoxConstraints constraints;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Match Parent'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded( // shares space constraint evenly with other Expanded
child: Center( // ← fills tight parent constraint & loosens ↓ child constraint ↓
child: Container( // got loose constraint from Center...
constraints: constraints, // can apply many additional constraints
color: Colors.lightBlueAccent.withOpacity(.3),
child: Text('Center > Container > Text')),
),
),
Expanded(
child: Container(
color: Colors.orangeAccent,
child: Wrap(
children: [
_button('default', null),
_button('*expand()', BoxConstraints.expand()),
_button('*tight(Size.infinite)', BoxConstraints.tight(Size.infinite)),
_button('tight(Size.zero)', BoxConstraints.tight(Size.zero)),
_button('tight(Size.fromHeight(100))', BoxConstraints.tight(Size.fromHeight(100))),
_button('tight(Size.fromWidth(100))', BoxConstraints.tight(Size.fromWidth(100))),
_button('tightForFinite(width: 100, height: 100)', BoxConstraints.tightForFinite(width: 100, height: 100)),
_button('loose(Size.infinite)', BoxConstraints.loose(Size.infinite)),
_button('tightFor(width: double.infinity)', BoxConstraints.tightFor(width: double.infinity)),
_button('tightFor(height: double.infinity)', BoxConstraints.tightFor(height: double.infinity)),
])
),
)
],
),
);
}
Widget _button(String label, BoxConstraints _constraints) {
bool _active = _constraints == constraints;
return Padding(
padding: const EdgeInsets.only(top:8, left: 8),
child: RaisedButton(
color: _active ? Colors.cyanAccent : null,
child: Text(label),
onPressed: () {
setState(() => constraints = _constraints);
},
),
);
}
}
MATCH_PARENT
FractionallySizedBox(
widthFactor: 1.0, // width w.r.t to parent
heightFactor: 1.0, // height w.r.t to parent
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
或
Container(
height: double.infinity,
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
或
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
或
Container(
constraints: BoxConstraints.expand(),
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
WRAP_CONTENT
Wrap(children: [
Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
])
或
Container(
constraints: BoxConstraints.tightFor(),
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
Match_parent,Wrap_content :
Row(
children: [
Expanded(
child: Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
),
])
Wrap_content,Match_parent :
Column(
children: [
Expanded(
child: Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
),
])