Flutter - 布局:正方形

2019-08-18  本文已影响0人  开心人开发世界

今天我们将使用Flutter创建以下布局。我们为什么要那样做?答案很简单:“练习变得完美”。

但是我们怎么能这样做呢?真的有可能像这样在彼此之上和之下扭曲方块吗?


我想到的第一种方法是使用九个方块,并相应地着色它们,如下所示:

但是可以使用更少的方块吗?也许是这样的:

上面的布局包含一个包装其他所有内容的列。在该列中,有两行。第一行有两个子项(红色和橙色),第二行有两列。第一列是绿色,第二列有两行,依此类推......

据我所知,橙色块不可能使用一个小部件,除非......我们使用stack,并将橙色块排列在其他块之上。

首先让我们创建上面的布局,之后,我们将看到如何使用橙色的stack。


在第一个中Row,我们将创建两个“ Container”并将它们中的每一个包装在一个Expanded小部件中,将flex因子设置为2表示红色Container,1表示黄色表示。我也将他们的身高设定为100。

使用“ 扩展”窗口小部件可以使“ 行”或“ 列”的子项展开以填充主轴中的可用空间(例如,水平方向为行,或垂直方向为)。如果扩展了多个子节点,则根据弹性因子将可用空间划分为多个子节点

main_page.dart

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Squares'),
      ),
      body: Column(
        children: <Widget>[
          Row(
            children: <Widget>[
              Expanded(
                flex: 2,
                child: Container(
                  height: 100,
                  color: Colors.red,
                ),
              ),
              Expanded(
                flex: 1,
                child: Container(
                  height: 100,
                  color: Colors.orange,
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

现在让我们创建第二行。

对于第二行,我们将使用另外两个Expanded小部件,第一个使用flex因子1,第二个使用flex因子将是2。

在这一行中,我们将紫色和橙色块放在两个Expanded小部件中。但我们不会为它们指定弹性因子。因此,他们将平等占用可用空间:

main_page.dart

Row(
  children: <Widget>[
    Expanded(
      flex: 1,
      child: Container(
        height: 200,
        color: Colors.green,
      ),
    ),
    Expanded(
      flex: 2,
      child: Column(
        children: <Widget>[
          Row(children: <Widget>[
            Expanded(
              child: Container(
                height: 100,
                color: Colors.purple,
              ),
            ),
            Expanded(
              child: Container(
                height: 100,
                color: Colors.orange,
              ),
            ),
          ],),
          Container(
            height: 100,
            color: Colors.blue,
          ),
        ],
      ),
    )
  ],
),

结果是:

要在每个块上显示白色数字,只需将Text小部件作为每个Container的子级,例如我们将拥有的红色Container:

main_page.dart

Expanded(
  flex: 2,
  child: Container(
    height: 100,
    color: Colors.red,
    child: Center(
      child: Text(
        "1",
        style: TextStyle(fontSize: 50, color: Colors.white),
      ),
    ),
  ),
),

请注意,我已将Text小部件包装在Center小部件中,以便文本显示在容器的中心:

我们差不多完成了,除了“2”号,它是居中的,但它没有居中!橙色块由两个不同的容器组成,数字“2”在下部容器中居中!

我们如何对齐此数字以使其居中?

我正在关注由Flutter的创作者创建的youtube上的一个频道,名为“ 本周的颤动小部件 ”。如果你还没有我完全建议你关注它!在上一集中,他们介绍了“Align”小部件,这对我们来说非常有用。

如下图所示,如果我们将对齐设置为(0,-1),对象将被放置在其容器内的顶部中心位置:

我用它来对齐下面橙色块内的文本。

我还尝试将对齐值设置为(0,-2.5)以将对象移动到其容器的上方(实际上是外部),并且它也起作用:

Expanded(
  child: Container(
    alignment: Alignment(0, -2.5),
    height: 100,
    color: Colors.orange,
    child: Text(
      "2",
      style: TextStyle(fontSize: 50, color: Colors.white),
    ),
  ),
),

结果:

现在让我们使用“Stack”小部件从头开始创建所有内容。


Stack的孩子从下往上定位。因此第一个应该在其他人之下的孩子是紫色的,第5个:

stack_page.dart

body: Stack(
  children: <Widget>[
    Container(
      color: Colors.purple,
      height: 300,
      child: Center(
        child: Text(
          "5",
          style: TextStyle(fontSize: 50, color: Colors.white),
        ),
      ),
    ),
  ],
),

现在让我们添加堆栈的第二个子块,块号为1:
stack_page.dart

Container(
  color: Colors.red,
  height: 100,
  width: MediaQuery.of(context).size.width * 2 / 3,
  child: Center(
    child: Text(
      "1",
      style: TextStyle(fontSize: 50, color: Colors.white),
    ),
  ),
),

请注意,我已使用MediaQuery该类获取屏幕的宽度,然后将其乘以2/3。或者,我可以将容器包装在0.66(2/3)的FractionallySizedBox类中,widthFactor以实现红色块的相同宽度。另请注意,堆栈的子项默认位于堆栈的左上角。因此,我们不需要对齐红色块:

现在我们将橙色块放在stack上:

Align(
  alignment: AlignmentDirectional.topEnd,
  child: Container(
    color: Colors.orange,
    width: MediaQuery.of(context).size.width * 1 / 3,
    height: 200,
    child: Center(
      child: Text(
        "2",
        style: TextStyle(fontSize: 50, color: Colors.white),
      ),
    ),
  ),
),

请注意,这一次,我将整个包装Container在一个Align小部件中,将小部件移动到堆栈的右上角。而这一次,橙色块的宽度是整个屏幕宽度的1/3:

添加和定位蓝色块有点棘手。因为如果你将它与“bottomRight”对齐,它最终会像这样:

这是因为我们没有为堆栈指定任何大小。因此它已经扩展到整个屏幕的大小。现在我们有两个选项来对齐蓝色块:

  1. 限制Stack高度。通过将其包装在SizedBox窗口小部件中,并将height属性设置为300。
  2. 手动对齐蓝色块。即使用alignment: Alignment(1, -0.22)而不是alignment: AlignmentDirectional.*bottomEnd*

我选择实施第一个:

body: SizedBox(
  height: 300,
  child: Stack(
    children: <Widget>[

结果:

将最后一个子项放在Stack上几乎与前一个相同,唯一的区别是它的宽度设置为屏幕宽度的1/3,它的位置是左下角,或者是BottmStart:

Align(
  alignment: AlignmentDirectional.bottomStart,
  child: Container(
    color: Colors.green,
    height: 200,
    width: MediaQuery.of(context).size.width * 1 / 3,
    child: Center(
      child: Text("4",
          style: TextStyle(fontSize: 50, color: Colors.white)),
    ),
  ),
),

结果:

最后的说明:

  1. MediaQuery课程对响应式设计非常有用。您可以使用它来查找屏幕的总大小,然后相应地设置小部件的大小。
  2. Expanded插件也是响应式设计非常方便,让你的部件由填充剩余的空间flex你指定的因素。
  3. 如果要将窗口小部件放置在其父窗口中,请将窗口小部件包装在窗口Align小部件中,并alignment相应地设置该属性。
  4. 如果没有为任何Stack的子项指定宽度和高度,默认情况下它们会将自身扩展到Stack的宽度和高度。
  5. 您还可以将Stack的每个子项包装在Positioned小部件中以对齐它们。

整个源代码可以在github上找到。

谢谢阅读!

翻译自:https://medium.com/@meysam.mahfouzi/flutter-layout-challenge-squares-3d0bc4c78793

上一篇下一篇

猜你喜欢

热点阅读