前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter 视图布局(三)

Flutter 视图布局(三)

原创
作者头像
林小帅
修改2019-11-11 11:28:10
1.3K0
修改2019-11-11 11:28:10
举报

各位少侠、小伙伴们久违了哈哈哈哈!(咕咕咕)

于近期有些事需要处理,未能及时更新非常抱歉!!!

之前的几篇中开头也把一些要注意的东西说完了,所以也不用那么多废话了,不多逼逼直接进入主题,就问你们开心不开心

那么这次就继续来说说关于视图布局的东西  Table、Wrap、Flow。相对于之前介绍的布局 Widget 这三个在实现上就需要编写一些对子元素控制逻辑了。

OK,那我们就一起来看看它们的究竟有哪些不同。

当然,惯例配合文章一同食用的代码已同步更新到 Github 地址:

https://github.com/linxsbox/myapp.git

01 - Tabel

首先进入眼帘的的是我们的一号选手 Table,也是大家都熟悉的选手。但几乎好像每一个编程语言具有UI绘制的部分都会有 Table。也许是它们对表格爱得深沉(大雾!)

Table 继承关系
Table 继承关系

依照惯例,我们现在需要做什么呢?

没错!当然是看源码部分啦。

Table 源码部分
Table 源码部分
  • List<TableRow> children 子元素列表 TableRow 类型
  • TableBorder border 表格的边框线
  • Map<int, TableColumnWidth> columnWidths 表格的列宽
  • FlexColumnWidth defaultColumnWidth Tabel 中列的宽度分配方式,基于  Flex
  • TableCellVerticalAlignment defaultVerticalAlignment Table 中单元格的垂直对齐方式
  • TextBaseline textBaseline 文字基线对齐方式
  • TextDirection textDirection 文字装饰属性

唉~这一看,是不是有几个属性已经眼熟了呢?那么熟悉的部分就不重复说明了。

children

你这一看,唉哟~是个老熟人,子元素列表嘛。上手就干 children: <Widget>[] 一顿猛敲。编辑器里的红色下划波浪线就像考试卷上老师画下的红叉,学生时代被考试支配的恐惧从心底如潮水般涌起,久久不能退去。

(什么?!你说你是学霸?!我不认识你!)

Tabale 错误的 children 类型
Tabale 错误的 children 类型

啪!啪!啪!(敲黑板)各位少侠,认真审题啊 List<TableRow> children 子元素列表 TableRow 类型,TableRow 类型啊!上一篇才说完的不要蒙头鲁莽怎么就不上心呢?你又不是 the shy。

Tabale 正确的 children 类型
Tabale 正确的 children 类型

columnWidths/defaultColumnWidth

你也许会奇怪为什么这两个属性会放到一起?

主要还是因为这两个属性所使用的类型的是 TableColumnWidth 这是 Table 里对列宽度设定而实现的类。我们来看一下它的源码部分。

我简单翻译一下:

TableColumnWidth 类用来描述 [RenderTable] 中的列应该有多宽。

如果需要将列设置为固定的大小,那么请使用 [FixedColumnWidth] 这是调整列宽消耗最小的方法。

其他相对消耗较小的列宽算法有 [FlexColumnWidth],它可以弹性分配所需的空间。

[FractionColumnWidth] 是基于 Table 的容器最大宽度。

当然除了以上提到列宽类型之外还有其他的列宽类型

  • IntrinsicColumnWidth 固有列宽,但其单元格以弹性方式计算
  • FixedColumnWidth 固定列宽
  • FractionColumnWidth 小部分列宽?(可能我英语水平不够实在是想不到好的中文解释)
  • FlexColumnWidth 弹性列宽,defaultColumnWidth 中默认类型
  • MaxColumnWidth 最大列宽,其参数类型为 TableColumnWidth
  • MinColumnWidth 最小列宽,其参数类型为 TableColumnWidth

不过这里要注意的是 FractionColumnWidth 单独使用的时候编译器会输出警告信息,虽然不会导致编译错误但是会导致渲染错误,表格无法正常渲染,以及列数据丢失。

IntrinsicColumnWidth 比较特殊,源码注释中说到,这是一种消耗非常大的列表宽度调整方式,它需要计算列中的每一个单元格的宽度来确定。而 FixedColumnWidth 是消耗最小的方式。

关于列宽的设置方式我已经在代码中全部列出来了,各位少侠可以更新 GitHub 来尝试不同的列宽设置组合。

TableCellVerticalAlignment

单元格的垂直对齐方式,这个也无需多说了。

  • top 顶部对齐
  • middle 垂直居中对齐
  • bottom 底部对齐
  • baseline 基线对齐
  • fill 充满 Cell

border

这个用起来和 css 的差不多,唯一需要注意的就是不要放错位置了,这个是 Table 下的属性之一。

Table(  // 表格边框  border: TableBorder.all(    width: 1.0, // 边框线宽度    style: BorderStyle.solid, // 边框线风格    color: Colors.red, // 边框线颜色  ),)

如果想要实现动态表格项的话还是需要使用编码的方式。

Table 动态实现单元格
Table 动态实现单元格

这样我们就可以通过以参数的方式来控制生成表格行列以及内容了。

02 - Wrap

在水平或垂直方向中显示多个子元素的部件。这该怎么理解呢?

Wrap 继承关系
Wrap 继承关系
  • List<Widget> children 子元素列表,注意看类型基本不是问题
  • Axis direction 决定主轴的方向
  • WrapAlignment alignment 主轴方向的行内子元素的对齐方式
  • WrapCrossAlignment crossAxisAlignment 副轴方向的行对齐方式
  • WrapAlignment runAlignment 副轴方向上的行内子元素对齐方式
  • VerticalDirection verticalDirection 垂直方向
  • TextDirection textDirection 文字方向
  • spacing 与下一个子元素的空间大小,默认为 0与下一个 widget 的空间大小,默认为 0与下一个 widget 的空间大小,默认为 0
  • runSpacing 行与下一行之间的空间大小,默认为 0

direction

决定了主轴的方向,有 horizontal 和 vertical 分别是横向和纵向,默认为horizontal,如果还对轴概念不理解也可以去看看布局(一)这一篇或者在代码里修改一下尝试看看结果。

alignment

主轴方向的行内子元素的对齐方式,即是决定的行内的子元素排列对齐的方式,可选值为轴线对齐和空间对齐的方式。

crossAxisAlignment

副轴方向的行对齐方式,在副轴上以行为单位的对齐方式,当然可选值也是轴线对齐和空间对齐的方式。

runAlignment

副轴方向上的行内子元素对齐方式,这里比较有意思的是,刚开始我还没以为没效果,因为我没有使用宽高属性来设定子元素的大小,后来才发现当子元素的宽高有差异的时候才能看得出来。

spacing & runSpacing

spacing 控制元素之间的间隔。

runSpacing 控制行之间的间隔。

这两个也不用特别说明,看图就明白了。

spacing & runSpacing
spacing & runSpacing

其实这有点类似 css 的 flex,只是使用了其中的一些概念,如果你对 flex 较为熟悉的话,那么使用 Wrap 使用起来也是没有太大难度。

03 - Flow

Flow 顾名思义,即流式布局,通过算法实现的布局部件。

Flow 继承关系
Flow 继承关系
Flow 源码部分
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个函数:

  • getSize 需要重写来控制子容器的大小,默认的情况下会尽可能的大,如果返回的大小不符合给定的约束,则会调整为最接近的大小,但同时仍然遵守约束。
  • getConstraintsForChild 重写以提供给每个子元素的布局约束控制。默认情况下子元素会遵守给定的约束,这些约束会用于调整容器的大小。
  • paintChildren 重写绘制子元素。可以按任意顺序绘制子对象,但是每个子元素最多只能绘制一次,容器会将子元素剪裁到自己的边界内。
  • shouldRelayout 重写此函数以便在需要布局子元素时时返回 true。它会比较当前的委托实现和给定的 oldDelegate的字段,如果它们不同则返回 true。
  • shouldRepaint 重写此函数以便在子元素需要时返回 true。这将重新绘制子元素,它会比较当前的委托实现和给定的 oldDelegate的字段,如果它们不同则返回 true。如果委托实现时提供了重绘的动画,那么此委托也可以触发重绘,这种基于动画机制触发的重绘比重新构建 Flow Widget 然后再更改委托更有效。即使此函数返回了 false 容器也依然可能重新绘制。

看完上面的内容你可能会一头雾水,这些都是什么鬼?那我要怎么实现呢?这里完全没说啊。

不要慌不要怕,其实呢在源码中已经给出实现例子了,我们只要去掉不需要的部分,留下最简单的绘制子元素的部分就Ok。

Flow delegate 属性实现例子
Flow delegate 属性实现例子

由源码中的例子可以看出,主要是实现了一个类,这个类继承了 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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01 - Tabel
  • 02 - Wrap
  • 03 - Flow
    • 结语
      • 最后总结
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档