各位少侠、小伙伴们久违了哈哈哈哈!(咕咕咕)
于近期有些事需要处理,未能及时更新非常抱歉!!!
之前的几篇中开头也把一些要注意的东西说完了,所以也不用那么多废话了,不多逼逼直接进入主题,就问你们开心不开心
那么这次就继续来说说关于视图布局的东西 Table、Wrap、Flow。相对于之前介绍的布局 Widget 这三个在实现上就需要编写一些对子元素控制逻辑了。
OK,那我们就一起来看看它们的究竟有哪些不同。
当然,惯例配合文章一同食用的代码已同步更新到 Github 地址:
https://github.com/linxsbox/myapp.git
首先进入眼帘的的是我们的一号选手 Table,也是大家都熟悉的选手。但几乎好像每一个编程语言具有UI绘制的部分都会有 Table。也许是它们对表格爱得深沉(大雾!)
依照惯例,我们现在需要做什么呢?
没错!当然是看源码部分啦。
唉~这一看,是不是有几个属性已经眼熟了呢?那么熟悉的部分就不重复说明了。
children
你这一看,唉哟~是个老熟人,子元素列表嘛。上手就干 children: <Widget>[] 一顿猛敲。编辑器里的红色下划波浪线就像考试卷上老师画下的红叉,学生时代被考试支配的恐惧从心底如潮水般涌起,久久不能退去。
(什么?!你说你是学霸?!我不认识你!)
啪!啪!啪!(敲黑板)各位少侠,认真审题啊 List<TableRow> children 子元素列表 TableRow 类型,TableRow 类型啊!上一篇才说完的不要蒙头鲁莽怎么就不上心呢?你又不是 the shy。
columnWidths/defaultColumnWidth
你也许会奇怪为什么这两个属性会放到一起?
主要还是因为这两个属性所使用的类型的是 TableColumnWidth 这是 Table 里对列宽度设定而实现的类。我们来看一下它的源码部分。
我简单翻译一下:
TableColumnWidth 类用来描述 [RenderTable] 中的列应该有多宽。
如果需要将列设置为固定的大小,那么请使用 [FixedColumnWidth] 这是调整列宽消耗最小的方法。
其他相对消耗较小的列宽算法有 [FlexColumnWidth],它可以弹性分配所需的空间。
[FractionColumnWidth] 是基于 Table 的容器最大宽度。
当然除了以上提到列宽类型之外还有其他的列宽类型
不过这里要注意的是 FractionColumnWidth 单独使用的时候编译器会输出警告信息,虽然不会导致编译错误但是会导致渲染错误,表格无法正常渲染,以及列数据丢失。
IntrinsicColumnWidth 比较特殊,源码注释中说到,这是一种消耗非常大的列表宽度调整方式,它需要计算列中的每一个单元格的宽度来确定。而 FixedColumnWidth 是消耗最小的方式。
关于列宽的设置方式我已经在代码中全部列出来了,各位少侠可以更新 GitHub 来尝试不同的列宽设置组合。
TableCellVerticalAlignment
单元格的垂直对齐方式,这个也无需多说了。
border
这个用起来和 css 的差不多,唯一需要注意的就是不要放错位置了,这个是 Table 下的属性之一。
Table( // 表格边框 border: TableBorder.all( width: 1.0, // 边框线宽度 style: BorderStyle.solid, // 边框线风格 color: Colors.red, // 边框线颜色 ),)
如果想要实现动态表格项的话还是需要使用编码的方式。
这样我们就可以通过以参数的方式来控制生成表格行列以及内容了。
在水平或垂直方向中显示多个子元素的部件。这该怎么理解呢?
direction
决定了主轴的方向,有 horizontal 和 vertical 分别是横向和纵向,默认为horizontal,如果还对轴概念不理解也可以去看看布局(一)这一篇或者在代码里修改一下尝试看看结果。
alignment
主轴方向的行内子元素的对齐方式,即是决定的行内的子元素排列对齐的方式,可选值为轴线对齐和空间对齐的方式。
crossAxisAlignment
副轴方向的行对齐方式,在副轴上以行为单位的对齐方式,当然可选值也是轴线对齐和空间对齐的方式。
runAlignment
副轴方向上的行内子元素对齐方式,这里比较有意思的是,刚开始我还没以为没效果,因为我没有使用宽高属性来设定子元素的大小,后来才发现当子元素的宽高有差异的时候才能看得出来。
spacing & runSpacing
spacing 控制元素之间的间隔。
runSpacing 控制行之间的间隔。
这两个也不用特别说明,看图就明白了。
其实这有点类似 css 的 flex,只是使用了其中的一些概念,如果你对 flex 较为熟悉的话,那么使用 Wrap 使用起来也是没有太大难度。
Flow 顾名思义,即流式布局,通过算法实现的布局部件。
嗯?这乍一看怎么才2个属性?难道如此简单?我劝你先不要盲目乐观,莫急。
@required
FlowDelegate delegate Widget 绘制子对象的委托,必须实现
List<Widget> children 子元素列表
children
很熟悉了,也就不再重复说明了,主要的是 delegate 部分。
delegate
delegate 的类型是 FlowDelegate,如果不写的话。
那么这个 delegate 到底是个什么东西呢?
在源码中的注释我可以翻译一下:
The delegate that controls the transformation matrices of the children.
用于控制子对象的变换矩阵的委托。
噢~原来这是一个委托,简单来说就是用于控制子元素的绘制的委托实现。如果不实现的话,那么子元素就无法进行绘制渲染了。
FlowDelegate 主要有如下5个函数:
看完上面的内容你可能会一头雾水,这些都是什么鬼?那我要怎么实现呢?这里完全没说啊。
不要慌不要怕,其实呢在源码中已经给出实现例子了,我们只要去掉不需要的部分,留下最简单的绘制子元素的部分就Ok。
由源码中的例子可以看出,主要是实现了一个类,这个类继承了 FlowDelegate,然后重写了 shouldRepaint 和 paintChildren 函数,shouldRepaint 还算简单,只要是菜单动画发生了变化则返回true,然后让子元素重新绘制。而 paintChildren 部分则是通过绘制的内容中获取子元素,然后再获取子元素的宽度,通过矩阵变换的方式来重绘子元素。
大致了解这个实现过程后,我们就来自己写一个 Flow。
在这里可看到并没有编写太多的代码,但是运行的时候就不会报错了。虽然没有将子元素的内容绘制在界面上,但是通过 for 循环已经取到了子元素的对象信息,这里控制台已经输出了子元素的大小信息。
接下来我们只要再将绘制部分的代码通过矩阵定位的方式,将子元素渲染到 Flow 容器中就可以在界面中看到子元素最终的身影了。
最终效果的话我就不展示了,少侠小伙伴们,可以自己更新修改代码尝试哟。
配合文章一同食用的代码已同步更新到 Github 地址:
https://github.com/linxsbox/myapp.git
整体来说除了 Flow 绘制部分稍微要理解一下,Table、Wrap就很常规了,不用考虑太多即可直接使用生成,但是如果想要更灵活的控制子元素的话那么一定是非 Flow 莫属,它可以使用矩阵的方式来进行对子元素的处理,例如说子元素高度不同的情况,就可以通过计算当前列高来确定下一个子元素的 y 轴位置。
感谢大家的喜欢!
欢迎 关注、留言、分享、转发、在看。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。