Flutter 布局

Kss

共 4669字,需浏览 10分钟

 · 2022-07-31

约束, 尺寸, 位置

今天我们来讲一下 Flutter 的基础布局,如果你之前是web前端开发转学 FLutter 的话,相信我, 这篇文章对你会有所帮助的(我自己刚学flutter的时候就因为带着web开发的思想踩了不少坑, 害,说多了都是泪). 话不多说, 咱们先来一个小例子热热身

1ed9b89d83a59cc982693a02b538a5c2.webp
void main(){
  runApp(myApp())
}

Scaffold myApp(){
 return Scaffold(
    appBar: AppBar(
      title: Text("Flutter Demo Home Page"),
    ),
    body: const FlutterLogo(size: 40),
    floatingActionButton: FloatingActionButton(
      onPressed: (){},
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ),
  )
}

我们在 body 添加了一个 FlutterLogo, 这个组件有个 size 属性可以用来控制它的大小,具体的效果如下图:

e2ddd12a03821fdedfecab1846df08c7.webp

现在 Logo 有了, 我想给它加一个背景色,提高整体的美感, 该怎么做呢?

具体代码如下:

Scaffold myApp(){
 return Scaffold(
    appBar: AppBar(
      title: Text("Flutter Demo Home Page"),
    ),
    body: Container(
      color: Colors.green,
      child: const FlutterLogo(size: 40),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: (){},
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ),
  );
}
bbf7a04058af4f6a6bea88851e6ff23b.webp

完美,想要的效果出来了, 但总感觉不够劲儿, 这个绿色看起来没有那种自由的感觉, 我还得把这片绿色儿再给放大点, 怎么做呢?

具体代码如下:

Scaffold myApp(){
 return Scaffold(
    appBar: AppBar(
      title: Text("Flutter Demo Home Page"),
    ),
    body: Container(
      height: 200,
      width: 200,
      color: Colors.green,
      child: const FlutterLogo(size: 40),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {},
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ),
  );
}
69c2927430b4d5ea44dd31c34050dfbf.webp

完美实现了那种充满自由气息的绿色背景, 这会儿可能有细心的读者就发现问题了:

  • 上面代码我只给Container 指定了宽高,并未给FLutterLogo做任何调整,但是为啥 FlutterLogo 也相对应的增大了啊? (这肯定是 Flutter 的 Bug, 先拿个小本本记下来)

上面那个也不算是个大问题, 忍忍也就过去了. 我们继续添加新需求, 这回我想把这个白色的背景换成个黑色的,直接上代码看结果!

Scaffold myApp(){
 return Scaffold(
    appBar: AppBar(
      title: Text("Flutter Demo Home Page"),
    ),
    body: Container(
      color: Colors.black,
      child: Container(
        height: 200,
        width: 200,
        color: Colors.green,
        child: const FlutterLogo(size: 40),
      ),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {},
      tooltip: 'Increment',
      child: const Icon(Icons.add),
    ),
  );
}
69c2927430b4d5ea44dd31c34050dfbf.webp

为什么背景颜色还是没有变啊? 这是什么情况?

a3ca8fc603e5fa115056341875d6cfc0.webp

肯定是我因为我没有给最外层的 Cotnainer 指定宽高, 所以它就按照它的child 的大小来填充了! 这次肯定没跑了, Flutter 不过如此跟 web 开发没啥区别嘛,这就修改代码3c82aa3b4879e6caad787ea23d8a9d02.webp

  Scaffold myApp(){
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Container(
          color: Colors.black,
          height: 400,
          width: 400,
          child: Container(
            color: Colors.green,
            width: 200,
            height: 200,
            child: const FlutterLogo(size: 40),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ),
      );
  }
a72969a2dbcd373b770b4758cf49d95d.webpe8c9bf201c6175d109fb05688e25c9ee.webp

为什么? 为什么绿色的 Container 变大了, FlutterLogo 怎么又变大了 ! 谁能告诉我这是为什  么! 我明明给子级的Container 设置了宽度和高度了啊, 为什么会不起作用呢 ?

Flutter 文档:  害, 但凡你稍稍看我一眼, 也不至于现在这样子啊.0804e5aeb516011ca0d9f8622ac88f2a.webp


相信对以上这些问题感到比较迷惑的读者, 应该是对 Flutter 的布局约束没有深入的了解,我们先抛抛开当前这个例子不谈, 先说一下这个布局约束, 布局约束是一个很常见的概念, 像是Ios的app 一般都是满足操作系统的布局约束的, 占满运行设备的整个屏幕

我们回过头来看下Flutter

  void main(){
    runApp(myApp())
  }

runApp() 这个函数就是把当前的任意一个 widget 作为整个程序的 root(根),比如说:

  void main() {
    runApp(Container(
      color: Colors.pink[200],
    ));
  }
d59418a3804e242ba7cb7c38c8d5569e.webp

整个屏幕全变成粉红色了, 这个就是操作系统对我们每个app的一个约束, 每个app的root(根) widget 都要遵循这个约束, 这个root(根) Container 就算我手动设置它的大小, 他也是不会有丝毫改变的, 示例如下

void main() {
  runApp(Container(
    width: 400,
    height: 400,
    color: Colors.pink[200],
  ));
}
d59418a3804e242ba7cb7c38c8d5569e.webp

既然root Container 大小不能改变的话, 我们再给它插入一个child Container, 并且设置宽高, 背景色设置为白色, 看看是啥效果:

  void main() {
    runApp(Container(
      width: 400,
      height: 400,
      color: Colors.pink[200],
      child: Container(
        color: Colors.white,
        width: 200,
        height: 200,
      ),
    ));
  }
72a70ee473ae05269bee4139ea7ce563.webp

整个页面全部变白了,root Container 不生效情有可原, 毕竟它要满足操作系统的布局约束, 但是按理说child Container 理论上来讲应该是可以不沾满屏幕, 但是为什么却占满了呢?

这是因为我们没有告诉 root Container 当 child Container 在比较小的情况下, 应该摆放在哪里, 这个时候我们给 child Container 再添加一个 Center widget (Center 能让子级widget居中摆放) 试试看

void main() {
  runApp(Container(
    width: 400,
    height: 400,
    color: Colors.pink[200],
    child: Center(
      child: Container(
        color: Colors.white,
        width: 200,
        height: 200,
      ),
    ),
  ));
}
87fbfd3a99a11f43f1c2b9fd1981a9a4.webp

__嗯!, 这个效果完美, 就是我们想要的 200 大小的一个Container, 这个时候我们再给 child Container 添加个 Flutter Logo 看看会发生什么样的现象

void main() {
  runApp(Container(
    width: 400,
    height: 400,
    color: Colors.pink[200],
    child: Center(
      child: Container(
        color: Colors.white,
        width: 200,
        height: 200,
        child: const FlutterLogo(size: 50),
      ),
    ),
  ));
}
26711da49fbb1a0b7abc41fb6316a9bb.webp

FlutterLogo 会和 child Container 一样大, 原因也是因为 我们没有告诉 Flutter parent widget 当FlutterLogo 在较小尺寸时如何摆放的原因, 这里我们同样的在添加一个 Center 就完美解决了 FlutterLogo 尺寸 跟随 父级尺寸的问题b4ec78e634be072af42376e6e5cfd899.webp

接下来让我们画张图, 来更加详细的了解一下布局约束

2f6da8fad6107a6057266ccc45bdb5ab.webp

看完这个图之后是不是茅塞顿开 ? 哈哈哈, 又可以愉快的开发Flutter了, 今天的分享就先到这里

5aeea4e623585e1127b6969f988132d4.webp


浏览 39
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报