使容器小部件垂直填充父级

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 小部件和RowcrossAxisAlignment: 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

以上是关于使容器小部件垂直填充父级的主要内容,如果未能解决你的问题,请参考以下文章

布局:如何在垂直布局中使一个小部件成为其余小部件的 3 倍

如何使 Gridstack.js 小部件垂直响应?

父级大小更改时如何更改子窗口小部件的大小?

所有小部件的颤振填充?

如何使小部件填充列中的剩余空间

如何在堆栈中垂直或水平居中小部件?