前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter 组件集录】SizedBox | 8 月更文挑战

【Flutter 组件集录】SizedBox | 8 月更文挑战

作者头像
张风捷特烈
发布2022-03-18 15:46:00
4990
发布2022-03-18 15:46:00
举报
一、认识 SizedBox 组件

源码中对 SizedBox 的介绍为:一个指定尺寸的盒子。那 SizedBox 为什么可以限定尺寸?背后区域限定的原理又是什么? 本文通过 SizedBox 来一窥布局约束奥秘的冰山一角。

1.SizedBox 基本信息

下面是 SizedBox 组件类的定义构造方法,可以看出它继承自 SingleChildRenderObjectWidget。可接受一个子组件,和区域的宽高。

2.SizedBox 的使用

如下,是一个 100*50SizedBox ,通过 ColoredBox 涂上蓝色,效果如下:

代码语言:javascript
复制
SizedBox(
  width: 100,
  height: 50,
  child: ColoredBox(
    color: Colors.blue.withAlpha(88)
  ),
),
3.区域分析

乍一看,不就是一个组件提供宽高来设置尺寸吗,似乎并没有什么好延伸的。但你有没有想过,为什么 SizedBox 有权力决定尺寸大小?它决定的区域一定有效吗?在分析之前,先了解一些前置知识:

任何组件的占位区域绘制内容最终都取决于 RenderObject 。而并非所有的组件都和 RenderObject 有关,只有 RenderObjectWidget 负责维护 RenderObject 。像 StatelessWidgetStatefulWidget 这种都是基于已有组件进行组合,往深层去看,他们都是基于某些 RenderObjectWidget 实现。

关于布局, RenderObject 有一个非常重要的属性: Constraints 类型的 constraints ,表示自身受到的区域约束限制。而 RenderBox 作为 RenderObject 的子类,拓展出了 size 的概念,绝大多数组件维护的渲染对象都是在 RenderBox 基础上进行拓展的。

下面来打开组件树,一起来看一下:

上面的 SizedBox 组件,它维护的 RenderObjectRenderConstrainedBox ,自身的约束为 [w(0,800) - h(0,600)] ,也就说明该渲染对象的大小必须在这此区间内。然后它会给子组件施加一个额外的约束 [w(100,100) - h(50,50)]

这样对于 ColoredBox 对应的渲染对象 _RenderColoredBox ,由于父级施加的额外约束,自身的约束也就变成 [w(100,100) - h(50,50)] 。也就说明该渲染对象的大小必须在这此区间内,即 _RenderColoredBox 的尺寸被限定为 (100,50)

_RenderColoredBoxsize 确定后,RenderConstrainedBox 会根据自身的约束和子节点的尺寸来确定自身的尺寸。这就是 SizedBox 的工作原理。

4、约束测试

为了更好地说明约束的作用,这里进行一下测试,在之前的案例的 SizedBox 外层通过 ConstrainedBox 组件添加添加一个 [w(20,20) - h(20,20)] 的强制约束。可以看出即使 SizedBox 设置了固定的宽高,但是在外层的约束之下,会优先满足父级约束。

代码语言:javascript
复制
[推论1] SizedBox 的最终尺寸会受到父级约束的影响,并非一定为指定值。
代码语言:javascript
复制
ConstrainedBox(
  constraints: BoxConstraints(
    minWidth: 20,
    maxWidth: 20,
    maxHeight: 20,
    minHeight: 20,
  ),
  child: SizedBox(
    width: 100,
    height: 50,
    child: ColoredBox(color: Colors.blue.withAlpha(88)),
  ),
);

我们再来看一下此时的组件树: 可以看出 SizedBox 维护的 RenderConstrainedBox 本身的约束区域为 [w(20,20) - h(20,20)] ,为子节点施加的额外约束为 [w(100,100) - h(50,50)] 。在 ColoredBox 维护的 _RenderColoredBox 中,约束区域为 [w(20,20) - h(20,20)] ,这也就觉得了其尺寸为 (20,20)

这样可以看出,渲染对象对子节点施加的额外约束 ,并不会完全作用于子节点。还会根据自身的约束情况,来确定子组件的最终约束。

三、SizedBox 的源码分析

SizedBox 继承自 SingleChildRenderObjectWidget ,就说明它需要维护一个 RenderObject 来实现功能。

在前面我们通过组件树可以看出,它维护的渲染对象是 RenderConstrainedBox 。从源码中可以看出, RenderConstrainedBox 构造时需要传入一个约束对象 BoxConstraints 。这里通过 BoxConstraints.tightFor 构造使用 widthheight 创建一个紧约束。

通过源码可以看出,这个构造的约束为: [w(width,width) - h(height,height)],也就是固定宽高约束。

SizedBox 除了普通构造之外,还有三个命名构造。如果已经了解上面的用法,那这三个也非常简单,都逃离不了对宽高的初始化。比如 .expand 会创建一个无限的约束,这样由于 推论1 ,其约束的尺寸就可以在父级的约束下,尽可能的大 。 .shrink 就是一个 [w(0,0) - h(0,0)]的限制,同理,会在父级的约束下,尽可能的小。

至于 RenderConstrainedBox 渲染对象的实现,将在后面的 ConstrainedBox 一文中进行介绍,毕竟 RenderConstrainedBox 的本命是 ConstrainedBox 。通过本文,你应该对 SizedBox 有了更深的认识,对布局约束、尺寸确定也认识了九牛一毛 。那本文到这里就结束了,谢谢观看,明天见~

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021/08/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、认识 SizedBox 组件
  • 1.SizedBox 基本信息
  • 2.SizedBox 的使用
  • 3.区域分析
  • 4、约束测试
  • 三、SizedBox 的源码分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档