使容器小部件垂直填充父级
Posted
技术标签:
【中文标题】使容器小部件垂直填充父级【英文标题】:Make container widget fill parent vertically 【发布时间】:2018-12-11 19:19:29 【问题描述】:TL;DR 需要容器填充垂直空间,以便它可以充当 ontap 侦听器。尝试了大多数解决方案,但似乎没有任何效果。
所以我想做的是让我的容器填满垂直空间,同时仍然具有固定的宽度。 Two first is what I have and third is what I want。这个想法是通过手势 ontap 侦听器使容器透明。如果有人对不同的解决方案有更好的想法,请随时提出建议。
Widget build(BuildContext context)
return new GestureDetector(
onHorizontalDragUpdate: _move,
onHorizontalDragEnd: _handleDragEnd,
child: new Stack(
children: <Widget>[
new Positioned.fill(
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Container(
child: new IconButton(
padding: new EdgeInsets.only(top: 16.0, bottom: 16.0, left: 24.0, right: 24.0),
icon: new Icon(Icons.warning),
color: Colors.black12,
onPressed: () ,
)
),
],
),
),
new SlideTransition(
position: new Tween<Offset>(
begin: Offset(0.0, 0.0),
end: const Offset(-0.6, 0.0),
).animate(_animation),
child: new Card(
child: new Row(
children: <Widget>[
new Container(
width: 20.0,
height: 20.0,
color: Colors.amber,
),
new Expanded(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_getListTile(),
_ifStoplineIsToBeShown()
],
),
)
],
)
),
),
],
)
);
考虑到我尝试了很多不同的东西但似乎没有任何效果,我很确定我错过了一些东西。
我还上传了一张带调试画的图片here。
PS。我知道我已将高度设置为固定值,但这是显示容器的唯一方法。
【问题讨论】:
onHorizontalDragStart
没有被调用吗?你的“固定宽度”在哪里?
【参考方案1】:
只需输入:double.infinity
。
如果你想让一个 Container 填满所有可用空间,你可以直接传入:
width: double.infinity,
height: double.infinity
说明:
在 Flutter 中,子小部件不能超出其父小部件施加的“布局约束”。在布局阶段,Flutter 引擎使用约束求解器自动将“越界”值更正为其父约束允许的值。
例如,如果您有一个 50x50 的 Container,并且对于它的子级,您传入另一个 300x300 的 Container,内部容器将自动更正为“不超过其父级”,即 50x50。因此,使用足够大的值将始终确保您“填充父级”。
事实上,即使BoxConstraints.expand()
在内部也利用了相同的想法。如果你打开expand()
的源代码,你会看到:
/// Creates box constraints that expand to fill another box constraints.
///
/// If width or height is given, the constraints will require exactly the
/// given value in the given dimension.
const BoxConstraints.expand(
double width,
double height,
) : minWidth = width ?? double.infinity,
maxWidth = width ?? double.infinity,
minHeight = height ?? double.infinity,
maxHeight = height ?? double.infinity;
因此,如果您绝对确定要填充所有空格,则可以直观地传入一个大于父级(或大于整个屏幕)的数字,例如double.infinity
。
【讨论】:
如果您只是模仿 Flutter 在后台所做的事情,那么对该逻辑的内部 Flutter 更改更有可能破坏您的代码。更好的做法是使用constraints: BoxConstraints.expand()
。
@andreyrk 谢谢!虽然您的陈述通常是正确的,但这里没有风险。 Flutter 引擎使用约束求解器将更大的值强制为其父级允许的值,这是 Flutter 布局工作原理背后的最基本原则之一。 BoxConstraints.expand()
只是利用了同样的事实。我已经更新了我的答案,试图更好地解释它。如果您不熟悉这些主题,您可能想了解 Flutter 引擎如何在后台执行布局。
这是要走的路。易于阅读和理解,无需向树中添加另一个小部件(至少在您看到的代码中)。【参考方案2】:
将容器的高度或宽度设置为 double.maxFinite
Container(
height: double.maxFinite,
width: 100,)
您可以让您的小部件采用容器小部件的全尺寸,然后将容器的高度和/或宽度设置为 double.maxFinite。这将使容器采用高度和/或宽度或其父小部件
【讨论】:
【参考方案3】:有很多答案建议使用两件事
-
约束:BoxConstraints.expand(),
高度:double.infinity,
但是这两个答案都会给你一个类似的错误
BoxConstraints 强制设置无限高。
我们可以通过计算屏幕的高度来避免这些
-
应用栏
顶部栏空间(在上面的应用栏上存在)
剩余屏幕
1.获取 MediaQuery
final mediaQuery = MediaQuery.of(context);
2。声明 AppBar Widget 并在 Scaffold App Bar 中使用相同的 App Bar 实例
final PreferredSizeWidget appBar = AppBar(
title: Text('Home'),
);
3.使用计算高度
Container(
width: mediaQuery.size.width,
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top),
color: Colors.red,
),
输出:
【讨论】:
【参考方案4】:我建议使用 Expanded 小部件(它允许我们避免使用 IntrinsicHeight 小部件),将它与 Container 的对齐属性结合起来,因此即使 Container 不是屏幕上唯一的一个,它也能正常工作。
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('Your text', textAlign: TextAlign.center))),
这样也可以避免潜在的应用程序崩溃,当您不小心将窗口小部件树的某些部分水平和垂直扩展为无穷大时,这种崩溃经常发生(这就是为什么您在许多情况下无法使用 BoxConstraints 窗口小部件)。
你可以在这里阅读更多关于在 Flutter 中传递约束的问题 - 必读:https://medium.com/flutter-community/flutter-the-advanced-layout-rule-even-beginners-must-know-edc9516d1a2
【讨论】:
【参考方案5】:截至 2020 年 1 月,最简单的方法是使用扩展小部件
Expanded(flex: 1,
child: Container(..),
),
https://api.flutter.dev/flutter/widgets/Expanded-class.html
【讨论】:
嘿,我一直在尝试这种方法似乎不起作用。你能帮我吗 ?如果我没有在其中设置容器的高度,小部件就会消失。 不需要设置flex: 1
,因为它是默认值
当我尝试在带有列的卡片小部件内扩展容器时,这对我有用。我在卡片末端的容器内有一个材质按钮,我想将它放在卡片的其余部分的中心。没有给出无穷大问题。谢谢!
这对我不起作用。应用父数据时引发以下断言:ParentDataWidget 使用不正确。 ParentDataWidget Expanded(flex: 1) 想要将 FlexParentData 类型的 ParentData 应用于 RenderObject,该 RenderObject 已设置为接受不兼容类型 ParentData 的 ParentData。通常,这意味着 Expanded 小部件具有错误的祖先 RenderObjectWidget。通常,扩展小部件直接放置在 Flex 小部件内。有问题的 Expanded 当前放置在 IntrinsicHeight 小部件中。【参考方案6】:
将容器拉伸到容器小部件中父级使用属性constraints:BoxConstraints.expand()
的全高。容器独立于子widget占据完整空间
Container(
color: Colors.green,
child: Text("Flutter"),
constraints: BoxConstraints.expand(),
)
容器详情请参考链接Container Cheat sheet
【讨论】:
因为这个比较简洁,应该用这个代替接受的答案吗? 完美解决方案 完美运行 错误:BoxConstraints 强制无限宽和无限高。 @RajaC 如果容器有一个 Singlechildscrollview() 作为父级,则它不起作用。【参考方案7】:诀窍是将IntrinsicHeight
小部件和Row
与crossAxisAlignment: CrossAxisAlignment.stretch
结合起来
这会强制 Row 的子级垂直扩展,但 Row 将占用尽可能少的垂直空间。
Card(
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: 20.0,
color: Colors.amber,
),
// Expanded(...)
],
),
)
)
【讨论】:
是否应该提到 IntrinsicHeight 对性能有影响? docs.flutter.io/flutter/widgets/IntrinsicHeight-class.html 我不这么认为。此处的警告主要是警告您不要在ConstraintBox
足够时使用它。这是预期的用例
明天试试,但这看起来很有希望。谢谢大家:)
这并没有填满我的垂直空间。对我有用的是将Container.height
设置为double.infinity
。以上是关于使容器小部件垂直填充父级的主要内容,如果未能解决你的问题,请参考以下文章