flutter widget:其他布局

作者: 浩林Leon | 来源:发表于2018-10-03 20:37 被阅读4次

1. Flex

如果你不确定需要具体的排列方向是水平还是垂直的时候,可以使用。(可以动态的根据不同的方向具体显示?)他表示子节点会在一维方向上显示。

Flex 允许你根据子节点的放置(水平或垂直)来控制轴。这被称作主轴。你如果事先直到具体的主轴,那么考虑使用Row或者Column,因为这不这么冗余。

如果需要让孩子展开填充可用的垂直空间,用Expanded包裹孩子。

实际上 ColumnRow 都是继承 Flex,并且实现了具体的差异化。

2. Expanded

Expanded 可以展开 RowColumn,或者Flex的子结点。

使用Expanded可以让RowColumnFlex的子节点展开来填充其主轴上的剩余可用空间(例如 Row的水平空间,Column的垂直空间)。如果多个子结点都被展开,则根据flex因子来分配的具体空间。

Expanded控件必须是RowColumnFlex的后代,从控件到其封闭的RowColumnFlex的路径必须只包含StatelessWidgets 或StatefulWidget这些,不能是其他类型的Widget(例如RenderObjectWidget)。

3. Flexible

用于控制RowColumnFlex的伸缩值。

实际上Expanded是继承 Flexible。使用Flexible小部件为RowColumnFlex的子部件提供了扩展以填充主轴中可用空间的灵活性(例如,水平地填充Row或垂直地填充Column),但与Expanded不同,Flexible不要求子部件填充可用空间。

Flexible控件必须是RowColumnFlex的后代,从控件到其封闭的RowColumnFlex的路径必须只包含StatelessWidgets 或StatefulWidget这些,不能是其他类型的Widget(例如RenderObjectWidget)。

4. SingleChildScrollView

一个可以滚动单个widget的框

只容纳一个widget,当空间大小不够的时候,里面的widget可以在主轴上滚动。
你如果需要在两个方向上收缩包装(在滚动轴和横轴)例如 dialog或者 pop-up菜单,在这种情况下,你可以用SingleChildScrollView包裹孩子ListBody

当您有一个子列表并且不需要跨轴收缩包装行为时,例如,一个始终是屏幕宽度的滚动列表,请考虑ListView,它比包含多个子列表体的ListBody或Column的SingleChildScrollView的效率要高得多。

简单的代码:使用一个 ColumnSingleChildScrollView

有时候,布局是围绕Column的灵活属性设计的,但是有些时候可能没有足够的空间来查看整个内容。这可能是因为一些设备具有异常小的屏幕,或者因为应用程序可以在纵横比不是最初设想的横向模式下使用,或者因为应用程序在分割屏幕模式下在小窗口中显示。无论如何,在singleChildScrollView中包装布局可能是有意义的。

然而,仅仅这样做通常会导致Column与SingleChildScrollView之间的冲突,Column通常试图尽可能地变大,而SingleChildScrollView为子视图提供了无限大的空间。

为了解决这个明显的冲突,有一些技术,如下所讨论的。这些技术应该只在通常期望内容适合屏幕时才使用,这样基于sliver的ListView或CustomScrollView的惰性实例化就不会提供任何性能优势。如果预期视口通常包含超出屏幕尺寸的内容,那么SingleChildScrollView将非常昂贵。

居中、间隔或对齐固定高度的内容

如果内容具有固定的(或内在的)维度,但是需要使用列的Flex布局模型进行分隔、居中或其他定位,那么可以使用以下技术向列提供最小维度,同时允许它在没有时收缩包装内容足够的空间来应用这些间距或对齐需要。

LayoutBuilder用于获得视口的大小(隐式地通过SingleChildScrollView看到的约束,因为视口通常增长以适应其最大高度约束)。然后,在滚动视图中,使用ConstrainedBox来设置Column的最小高度。

Column没有展开的子元素,因此它不是从BoxConstraints.maxHeight获取无限的高度(viewport不提供最大高度约束),而是自动尝试收缩以适合其子元素。但是,它不能小于其BoxConstraints.minHeight,因此它变为ConstrainedBox提供的最小高度和子节点高度的总和。

如果子节点不足以适应最小大小,那么Column最终将得到一些剩余空间来分配,这是由Column.mainAxisAlignment参数指定的。

 body: new LayoutBuilder(
          builder: (BuildContext context, BoxConstraints viewportConstraints) {
        return new SingleChildScrollView(
          child: new ConstrainedBox(
            constraints:
                new BoxConstraints(minHeight: viewportConstraints.maxHeight),
            child: new Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                new Container(
                  color: Colors.yellow,
                  height: 120.0,
                ),
                new Container(
                  color: Colors.red,
                  height: 200.0,
                )
              ],
            ),
          ),
        );
      }),

在这个例子中,子结点被平均地间隔开来,除非没有更多的空间;在没有更多空间情况下,他们垂直堆叠并滚动。

有足够空间 空间不足,垂直堆叠

当使用这种技术时,Expanded和Flexible是没有用的,因为在这两种情况下,“可用空间”都是无限的(因为这在视口中)。下一节描述了一种提供最大高度约束的技术。

展开内容以适应可视区域

下面的示例建立在前一个示例上。除了为子列提供最小维度之外,还使用IntrinsicHeight小部件强制列与其内容一样大。这个约束与前面讨论的ConstrainedBox约束相结合,以确保该列要么与viewport一样大,要么与内容一样大,无论哪个最大。
必须使用这两个约束来获得期望的效果。如果只指定了IntrinsicHeight,那么当其子视图小于整个屏幕时,该列就不会增长到适合整个视图。如果仅使用视口的大小,则如果儿童大于视口,则列将溢出。

///LayoutBuilder +SingleChildScrollView+IntrinsicHeight+Expanded
      body: new LayoutBuilder(
          builder: (BuildContext cotext, BoxConstraints viewportConstraints) {
        return SingleChildScrollView(
          child: new ConstrainedBox(
            constraints:
                new BoxConstraints(minHeight: viewportConstraints.maxHeight),
            child: new IntrinsicHeight(
              child: new Column(
                children: <Widget>[
                  new Container(
                    color: Colors.yellow,
                    height: 120.0,
                  ),
                  new Expanded(
                      child: new Container(
                    color: Colors.red,
                    height: 50.0,
                  ))
                ],
              ),
            ),
          ),
        );
      }),
image.png

这种技术相当昂贵,因为它或多或少要求对视口的内容进行两次布局(一次找到它们的内在尺寸,一次实际布局它们)。因此,列中的小部件的数量应该保持较小。或者,具有已知维度的子集可以封装在具有紧密垂直约束的SiezedBox中,以便当内部大小调整算法到达子树的那些部分时可以缩短计算。

所以可以看看其他的控件
  • ListVIEW,它处理滚动列表中的多个子项。
  • GRIDVIEW,它处理滚动网格中的多个子类。
  • PageView,一个可滚动的,一页一页地工作。
  • Scrollable,处理任意滚动效果。

相关文章

网友评论

    本文标题:flutter widget:其他布局

    本文链接:https://www.haomeiwen.com/subject/liozoftx.html