内容简介:在Flutter中,号称一切皆widget,手势是Widget,动画是Widget,UI更是Widget,今天我们就来说说Widgets里比较特殊的一个,Container。Container初用起来很简单,但是里面的逻辑又有些复杂,我也不敢说完全吃透,所以本文初期版本还是以总结网上各种文章为主,再加上自己的理解,如果有不对的地方,请一定指出
在Flutter中,号称一切皆widget,手势是Widget,动画是Widget,UI更是Widget,今天我们就来说说Widgets里比较特殊的一个,Container。
1. 参考文献
Container初用起来很简单,但是里面的逻辑又有些复杂,我也不敢说完全吃透,所以本文初期版本还是以总结网上各种文章为主,再加上自己的理解,如果有不对的地方,请一定指出
Dealing with box constraints in Flutter
Flutter — Container Cheat Sheet
What is a Container in Flutter?
Container Widget with example Flutter Tutorial
Understanding Flutter Layout (Box)Constraints
2. 介绍
在flutter中,所有的功能都被分散成单一功能的widget,比如居中有Center,边框有Padding,文字是Text,手势是GestureDetector,他们各自维护一个功能,但是我们商业App的UI都很精美,如果要实现一个很好的布局,需要嵌套非常多的布局Widget,所以Container应运而生:
A convenience widget that combines common painting, positioning, and sizing widgets.
官方文档一语道破了container复杂的原因,它是一个便利部件,融合了绘图、定位和大小部件,据我所知,可以设置大小,背景颜色,边框,圆角,阴影,渐变,而且大小可以有很多种情况,时而依赖于父部件,时而依赖于子部件,时而依赖于自己,所以我们稍后会重点说一说Container的布局(尺寸规则,宽高)。
3. Widget渲染流程
flutter是树状渲染结构,首先从根结点开始渲染,从上到下传递约束,直到最终的叶子节点(没有子节点了),然后叶子节点根据约束确定自身大小,然后将大小返回给上级结点,然后上一级根据叶子节点的尺寸,决定自己的大小,再返回上一级,最终根节点确定了大小。之后,根结点逐级往下摆放子节点的位置(根据子节点及子节点兄弟节点的大小和偏移量)。
4. Container渲染流程
根据官网的介绍,Container会首先使用设置的padding来围绕子部件,然后对padding的大小添加额外的约束(如果非空),然后容器被外部的空白区域(margin)包围。在绘制过程中,Container首先应用变换(transform),然后绘制装饰(decoration)来填充区域,接着绘制子部件,最后绘制前景装饰(foregroundDecoration),同时填充该区域。
decoration和foregroundDecoration是填充配置,前者是在子部件之下,后者是子部件之上,可以设置填充颜色,边框,填充形状,阴影,渐变色,背景图片等。
如果Container的约束是有限制的,那么没有子部件的Container会尝试尽可能大,如果Container的约束是没有限制的(unbounded),它就会尽可能小。
有子部件的Container,根据子部件确定自己的大小。
5. 有无限制约束
到底什么是有限制约束和无限制约束呢,各种部件又都是哪种约束呢?
在flutter中,widgets由底层的RenderBox渲染盒渲染,父组件向渲染盒提供约束条件,然后渲染盒用这些约束调整自己的尺寸,约束(Constraint)由最大和最小的宽高组成,尺寸(Size)由特定的宽高组成。
通常来说,有三种处理约束的盒子:
- 尽可能大:Center和ListView等
- 和子部件一样大:Transform和Opacity等
- 特定大小:Image和Text等
- 特殊情况:Row和Column由其给定的约束决定,Container由其构造函数的参数决定
但约束有时会变得紧凑,意思是它没有留给渲染盒子自行决定尺寸的余地(例如最大宽度和最小宽度相等,那允许的宽度是个固定值),例如App这个Widget,它的约束被设置为固定的应用程序内容大小(也就是整个屏幕)。而在Flutter中,很多的widget,尤其是只能有一个子部件的widget,会传递自己的约束到子部件。也就是说,如果你在App根渲染树里嵌套了一系列widget,他们将会因为紧凑的约束,一级级地贴着。
但是有些widget会使约束宽松,意思是最大的约束保留,但是最小的约束移除了,比如Center。
5.1 无限制约束
- 在某些情况下,赋给widget的约束是无限制(unbounded)的,或者说是无限(infinite)的。也就是说,最大宽度和最大高度,都是double.INFINITY。
- 一个尝试尽可能大的widget,遇到无限制约束的时候,是不会起作用的,因为它不知道到底该有多大,在debug模式下,就会抛出异常。
- 最常见的拥有无限制约束的情况,就是嵌入在弹性盒子里面,比如Row,Column或者可以滚动的区域(ListView或者其他ScrollView子类)。
需要指出的是,ListView会在其交叉方向扩张到父部件边界,例如一个纵向滚动的列表,在横向会尽量和父部件一样宽。 当你在横向滚动列表里,嵌入一个纵向滚动列表的时候,纵向列表会尽可能宽,也就是无限宽,因为横向列表是无尽宽的,这就会异常。
另外,弹性盒子(Row和Column)在有限制和无限制约束的情况下,表现出来的行为也不同。
- 在有限制的约束时,他们会在其方向上尽可能大。
- 在无限制约束时,他们会在其方向上适应他们子组件(包住子组件)。这种情况下,你不能在弹性盒子里用Expanded,因为这是将无法确定部件大小。
6. Container布局(尺寸规则)
因为Container集合了其他部件的功能,所以它的布局有些复杂,简而言之,按照顺序,Container会:
- 遵循对齐规则
- 为子部件调整自身大小
- 遵循宽高和约束
- 然后Container尝试尽可能小。
6.1 来看看官方文档的解释(这个解释看不懂就算了,有点啰嗦):
- 如果Container没有子部件,没有宽高,没有约束,并且父部件提供了无限制约束(unbounded constraints),Container会尽可能小。
- 如果Container没有子部件,没有对齐规则,但是提供了高度、宽度或者约束,那么Container会在遵循宽、高、约束和父部件约束的情况下,尽可能小。
- 如果Container没有子部件,没有宽高,没有约束,没有对齐,但是父部件提供了有限制约束,那么Container会扩张以适应(fit)父部件约束
- 如果Container有一个对齐规则,并且父部件提供了无限制约束,那么Container会尝试调整自己来包围子部件
- 如果Container有一个对齐规则,而且父部件提供了有限制约束,那么Container会尝试扩张以适应(fit)父部件,然后根据对齐方式,将子部件置于其内
- 另外,Container有子部件,但是Container没有宽高、约束、对齐规则,那么Container会传递父部件的约束到其子部件,然后调整自身来匹配子部件。
- margin和padding也会影响布局,decoration会隐性增加padding(比如设置border)。
- 默认是尽可能大
6.2 我们来总结一下:
maxWidth | maxHeight | 约束 | 有无子组件 | 布局规则 |
---|---|---|---|---|
有值 | 有值 | 有限制 | 无 | 尽可能大 |
有值 | 无值 | 高度无限制,宽度有限制 | 无 | 高度尽可能小,宽度尽可能大 |
无值 | 有值 | 高度有限制,宽度无限制 | 无 | 高度尽可能大,宽度尽可能小 |
无值 | 无值 | 无限制 | 无 | 尽可能小 |
都行 | 都行 | 都行 | 有 | 在满足约束的前提下尽可能小 |
6.3 例子
没有子组件,有约束,尽可能大↓
没有子组件,父组件约束最大宽度是屏幕宽度,最大高度是无限,自己的约束最小宽度是100,最小高度是100,则高度尽可能小到100,宽度尽可能大到屏幕宽度↓
父组件最大约束是屏幕宽高,自己是固定宽度100,则宽度是100,高度尽可能大到屏幕高度↓
自己没有设置约束,有子组件,所以自己包住子组件↓
自己设置固定高度100,宽度没有约束,有子组件,则高度为100,宽度包住子组件↓
有子组件,自己的高度是固定100,宽度设置为无限,则高度为100,宽度是父组件的约束屏幕宽度↓
有子组件,设置最小宽高为无限,则大小为屏幕大小↓
7. 总结
Container应该是flutter中最灵活的布局widget,大家一定要善用Container,用巧妙的方式处理布局,否则可能会让代码可读性变差,难以维护
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Flutter布局篇(1)--水平和垂直布局详解
- FlexBox 布局详解
- FlexBox 布局详解
- Android FlexboxLayout 布局详解
- Flutter 完整开发实战详解(十六、详解自定义布局实战)
- 图文详解 Java 对象内存布局
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。