flutterbox的简单介绍

Flutter 之 可滚动组件 -- 理论知识点(十四)

Flutter 中有两种布局模型:

从网站建设到定制行业解决方案,为提供网站设计制作、成都网站设计服务体系,各种行业企业客户提供网站建设解决方案,助力业务快速发展。成都创新互联公司将不断加快创新步伐,提供优质的建站服务。

基于 RenderBox 的盒模型布局。

基于 Sliver ( RenderSliver ) 按需加载列表布局。

通常可滚动组件的子组件可能会非常多、占用的总高度也会非常大;如果要一次性将子组件全部构建出将会非常昂贵!为此,Flutter中提出一个Sliver(中文为“薄片”的意思)概念,Sliver 可以包含一个或多个子组件。Sliver 的主要作用是配合:加载子组件并确定每一个子组件的布局和绘制信息,如果 Sliver 可以包含多个子组件时,通常会实现按需加载模型。

只有当 Sliver 出现在视口中时才会去构建它,这种模型也称为“基于Sliver的列表按需加载模型”。可滚动组件中有很多都支持基于Sliver的按需加载模型,如 ListView 、 GridView ,但是也有不支持该模型的,如 SingleChildScrollView 。

Flutter 中的可滚动主要由三个角色组成: Scrollable 、 Viewport 和 Sliver :

具体布局过程:

比如有一个 ListView,大小撑满屏幕,假设它有 100 个列表项(都是RenderBox)且每个列表项高度相同,结构如图6-1所示:

图中白色区域为设备屏幕,也是 Scrollable 、 Viewport 和 Sliver 所占用的空间,三者所占用的空间重合,父子关系为:Sliver 父组件为 Viewport,Viewport的 父组件为 Scrollable 。注意ListView 中只有一个 Sliver,在 Sliver 中实现了子组件的按需加载。

其中顶部和底部灰色的区域为 cacheExtent,它表示预渲染的高度,需要注意这是在可视区域之外,如果 RenderBox 进入这个区域内,即使它还未显示在屏幕上,也是要先进行构建的,预渲染是为了后面进入 Viewport 的时候更丝滑。cacheExtent 的默认值是 250,在构建可滚动列表时我们可以指定这个值,这个值最终会传给 Viewport。

用于处理滑动手势,确定滑动偏移,滑动偏移变化时构建 Viewport,我们看一下其关键的属性:

在可滚动组件的坐标描述中,通常将滚动方向称为主轴,非滚动方向称为纵轴。由于可滚动组件的默认方向一般都是沿垂直方向,所以默认情况下主轴就是指垂直方向,水平方向同理。

Viewport 比较简单,用于渲染当前视口中需要显示 Sliver。

需要注意的是:

Sliver 主要作用是对子组件进行构建和布局,比如 ListView 的 Sliver 需要实现子组件(列表项)按需加载功能,只有当列表项进入预渲染区域时才会去对它进行构建和布局、渲染。

Sliver 对应的渲染对象类型是 RenderSliver,RenderSliver 和 RenderBox 的相同点是都继承自 RenderObject 类,不同点是在布局的时候约束信息不同。RenderBox 在布局时父组件传递给它的约束信息对应的是 BoxConstraints ,只包含最大宽高的约束;而 RenderSliver 在布局时父组件(列表)传递给它的约束是对应的是 SliverConstraints 。关于 Sliver 的布局协议,我们将在本章最后一节中介绍。

几乎所有的可滚动组件在构造时都能指定 scrollDirection (滑动的主轴)、 reverse (滑动方向是否反向)、 controller 、 physics 、 cacheExtent ,这些属性最终会透传给对应的 Scrollable 和 Viewport,这些属性我们可以认为是可滚动组件的通用属性,后续再介绍具体的可滚动组件时将不再赘述。

可滚动组件都有一个 controller 属性,通过该属性我们可以指定一个 ScrollController 来控制可滚动组件的滚动,比如可以通过ScrollController来同步多个组件的滑动联动。由于 ScrollController 是需要结合可滚动组件一起工作,所以本章中,我们会在介绍完 ListView 后详细介绍 ScrollController。

Scrollbar是一个Material风格的滚动指示器(滚动条),如果要给可滚动组件添加滚动条,只需将Scrollbar作为可滚动组件的任意一个父级组件即可,如:

Scrollbar 和 CupertinoScrollbar 都是通过监听滚动通知来确定滚动条位置的。关于的滚动通知的详细内容我们将在本章最后一节中专门介绍。

CupertinoScrollbar是 iOS 风格的滚动条,如果你使用的是Scrollbar,那么在iOS平台它会自动切换为CupertinoScrollbar

Flutter(56):Layout组件之OverflowBox

对其子项施加不同约束的widget,它可能允许子项溢出父级。

下一节:Layout组件之SizedOverflowBox

2020-05-15 flutter BoxConstraints and layout

在出现布局错误时能尽快找到错误原因。

以下是对关键内容的翻译和注解。

flutter的布局模型是“一步布局模型”(one-pass layout model),在渲染树中,向下treewalk传递给子 盒约束,然后再向上treewalk将计算好的几何形状(比如高度、宽度等)传递给父。我理解one-pass layout model就是一遍就将布局计算好。不会多次treewalk去计算布局,或多次重绘(repaint)并多次计算布局。

计算的好的几何形状必须符合盒约束的要求。

盒约束有四个值,minWidth,maxWidth,minHeight,maxHeight,符合盒约束的意思就是说 计算出的宽高必须在最大值和最小值之间 。

我猜测,在将盒约束向子传递的过程中,子会根据父的盒约束,设置自己的盒约束,而不是单纯的继承父的盒约束。稍后结合Flex布局可以解释。

盒约束的最小值和最大值相等。因此在tight约束下的子的高宽将等于父的高宽,也就是说子是紧紧(tight)贴着父的。

盒约束的最小值为0,也就是说子可以是小于盒约束最大值的任何值,也就是说子是不紧贴(松的,loose)父的。

盒约束的最大值不是infinite(无穷大)

盒约束的最大值是infinite(无穷大)

盒约束的最小值是infinite(无穷大),他的子的宽或高只能取无穷大。

子的宽高(Size)符合盒约束的要求。

以下摘抄原文档并翻译,并加以分析。为了关注要点, 忽略crossAxis方向(水平方向)的处理 。

以下图为Column布局实例。

给column布局进行了以下6步操作

首先给每个非flex子元素,设置竖直方向unbounded(无界)的盒约束。结合图片,也就是将1、2两个子设置好竖直方向无界的盒约束。示例中1和2设置了高度,因此一共占用高度是5+3=8.

按flex的比例给flex元素分配剩余的空间。因为示例只有一个flex元素,即3号元素,因此将占有剩余全部空间,高度是20-5-3 = 12。

在第二步中分配好空间的flex元素,给他设置的盒约束不是竖直方向unbounded(给非flex元素设置的是竖直方向unbounded),而是有界的盒约束,盒约束的maxHeight是12,即第二步中被分配的高度。

水平方向不解释了。高度设置完了他去设置宽度。

Column组件的总高度是由mainAxisSize属性决定的,如果值是MainAxisSize.max,Column的高度就是Column的盒约束的maxHeight值,示例中我们给Column设置了高度为20的bounded盒约束,假设Column.mainAxisSize=MainAxisSize.max,那么Column的高度就是20.如果mainAxisSize=MainAxisSize.min,Column的高度将由其子元素的高度和决定。假设3号flex元素不设置成flex元素,而是固定高度为8,那么Column的高度就是5+3+8=16.

设置子元素的位置,即设置靠左,靠右,居中,分散等,与本示例关系不大。

根据第一步,inner column被outer column设置了无界(unbounded)的盒约束,Column会紧包children,而inner column的Expanded要撑开以占用inner column的剩余空间,这就冲突了。

解决方案:给inner column设置有界的盒约束即可。比如给inner column外包一层有高度的Container。

下面这种方案,给inner column包一层Expanded也可以,是因为在outer column中,Expanded会被设置成有界的盒约束(结合第三步),因此Expanded就可以向外扩展(expand)了。


网页题目:flutterbox的简单介绍
分享URL:http://azwzsj.com/article/dsdeeeo.html