前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从Container尺寸之谜看Flutter的渲染规则

从Container尺寸之谜看Flutter的渲染规则

作者头像
用户1907613
发布2019-04-09 14:19:51
1.7K0
发布2019-04-09 14:19:51
举报
文章被收录于专栏:Android群英传

Container是Flutter中的一个非常基础且重要的组件,而且是一个非常有用的胶水组件,它可以作为很多效果的过渡容器,掌握Container的使用对理解Flutter的布局是非常有帮助的。

在阅读下面的文章之前,还请读者们先思考下面几个问题。

  • 在不设置Container宽高的前提下,如果Container没有Child,那么它的尺寸是多少?
  • 在不设置Container宽高的前提下,如果Container有Child,那么它的尺寸又是多少?
  • 如果Container有Child,且设置了Alignment,那么它的尺寸又是多少?
  • 分别在MaterialApp和Scaffold中设置Container,尺寸展示会有不同吗?

Container没有Child

先来看看最简单的情况,如果Container没有Child,代码如下所示。

1. import 'package:flutter/material.dart';

2.

3. void main() => runApp(MaterialApp(

4. title: 'Travel',

5. home: HomePage(),

6. ));

7.

8. class HomePage extends StatelessWidget {

9. @override

10. Widget build(BuildContext context) {

11. return Scaffold(

12. appBar: AppBar(

13. title: Text('Container'),

14. ),

15. body: Container(

16. color: Colors.red,

17. ),

18. );

19. }

20.}

这种情况下,Container的展示如下图所示。

可以发现,Container会尽可能大的占据父布局的尺寸。

Container有Child

当Container有Child的时候,代码如下所示。

1. import 'package:flutter/material.dart';

2.

3. void main() => runApp(MaterialApp(

4. title: 'Travel',

5. home: HomePage(),

6. ));

7.

8. class HomePage extends StatelessWidget {

9. @override

10. Widget build(BuildContext context) {

11. return Scaffold(

12. appBar: AppBar(

13. title: Text('Container'),

14. ),

15. body: Container(

16. color: Colors.red,

17. child: Text('Text in Container'),

18. ),

19. );

20. }

21.}

这种情况下,展示效果如下图所示。

可以发现,Container使用了Child的尺寸。

Container有Child并设置Alignment

Container可以给Child设置对齐方式,因此,在有Child的情况下,设置下Alignment,代码如下所示。

1. import 'package:flutter/material.dart';

2.

3. void main() => runApp(MaterialApp(

4. title: 'Travel',

5. home: HomePage(),

6. ));

7.

8. class HomePage extends StatelessWidget {

9. @override

10. Widget build(BuildContext context) {

11. return Scaffold(

12. appBar: AppBar(

13. title: Text('Container'),

14. ),

15. body: Container(

16. color: Colors.red,

17. child: Text('Text in Container'),

18. alignment: Alignment.center,

19. ),

20. );

21. }

22.}

这种情况下,Container的展示如下图所示。

可以发现,Container占据父布局的最大尺寸,并根据Alignment设置Child的显示位置。

在MaterialApp的Home属性中设置指定宽高的Container

前面的例子都是在Scaffold中设置的Container,那么如果直接在MaterialApp中设置Container呢?代码如下所示。

1. import 'package:flutter/material.dart';

2.

3. void main() => runApp(MaterialApp(

4. title: 'Travel',

5. home: HomePage(),

6. ));

7.

8. class HomePage extends StatelessWidget {

9. @override

10. Widget build(BuildContext context) {

11. return Container(

12. width: 300,

13. height: 300,

14. color: Colors.red,

15. );

16. }

17.}

在上面的代码中,Container被设置为固定宽高,如果在Scaffold中设置的Container,那么Container的宽高会被限定为具体的数值,但运行上面的代码,可以发现,在MaterialApp中,固定宽高的Container展示效果如下所示。

可以发现,设置的固定宽高并没有生效。

很奇怪是吗?下面继续给这个Container外面增加一个Center组件,代码如下所示。

1. import 'package:flutter/material.dart';

2.

3. void main() => runApp(MaterialApp(

4. title: 'Travel',

5. home: HomePage(),

6. ));

7.

8. class HomePage extends StatelessWidget {

9. @override

10. Widget build(BuildContext context) {

11. return Center(

12. child: Container(

13. width: 300,

14. height: 300,

15. color: Colors.red,

16. ),

17. );

18. }

19.}

同样是在MaterialApp中,同样是指定Container的固定宽高,这个时候,Container展示了正确的设置尺寸,展示效果如下图所示。

看完上面的例子,是不是发现原本以为完全掌握了的Container,尽然变得这么诡异?

其实可以总结下,Container的布局规则如下。

如果Container组件没有Child,也没有Alignment,那么Container会在给定的约束,例如指定宽高、Constraints的约束下,尽可能小的展示,其它情况下,会尽可能大的占据父布局空间。

Flutter的布局规则

Flutter的UI设计与其它语言一样,需要开发者对每个组件的布局行为烂熟于心,做到胸有成竹,这样才能在设计界面的时候,将设计稿完全转换为代码,如果不了解具体的布局行为,就会在布局时模棱两可,花费多余的时间进行调试和分析,所以,掌握Flutter的布局规则和行为,是学习Flutter组件非常重要的一步。

Flutter的渲染过程与AndroidView的渲染过程类似但又稍有不同,这里不详细讲解Flutter的渲染过程,只单独讲解下Flutter组件之间的Layout过程,也就是Flutter是如何确定一个组件的位置、尺寸等布局信息的。

Flutter的Widget也是一个树形结构,与Android View Tree类似,一个完整的布局过程分为下面几个步骤。

  1. 根节点Widget向下分发自身的布局约束
  2. 根据收到的布局约束和自身布局约束,生成新的约束并继续向下分发
  3. 一直到树的叶子节点,Widget将生成的约束向上传递给父节点
  4. 根据收到的布局约束和自身布局约束,生成新的约束并继续向上传递

可以发现,Flutter的Layout过程也是一个深度优先遍历的过程,借助这一流程,回过头来看下上面提到的Container的布局行为。

首先,Container自身的布局约束为:最大尺寸为屏幕尺寸,当前尺寸为屏幕尺寸。

Container向下传递这个约束行为,而当Container没有Child的时候,就不会收到Child生成的新的布局约束,因此就使用了现有的布局约束,显示为屏幕宽高。

而当Container有Child的时候,Container收到了Child的尺寸约束,即Child自己的宽高,例如100x100,那么Container就会根据这一新的约束,修改自己的约束,将当前尺寸设置为Child的尺寸,这也就是为什么有Child的Container会展示出Child的尺寸的原因。

那么为什么MaterialApp和Scaffold的行为也不一样呢?很好理解,因为MaterialApp和Scaffold本身的约束设置就不一样,MaterialApp的Home Widget会被强制设置为屏幕的宽高,并作为一个固定尺寸。因此,在最后一个例子中,借助一个Align的组件,就可以完成Container的固定尺寸效果,原因是,此时Container已经不是MaterialApp的Child了,而Align组件本身就是会设置为父布局的最大尺寸,所以Container的宽高设置生效了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 群英传 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Container是Flutter中的一个非常基础且重要的组件,而且是一个非常有用的胶水组件,它可以作为很多效果的过渡容器,掌握Container的使用对理解Flutter的布局是非常有帮助的。
    • Container没有Child
      • Container有Child
        • Container有Child并设置Alignment
          • 在MaterialApp的Home属性中设置指定宽高的Container
            • Flutter的布局规则
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档