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

Flutter 视图布局(一)

原创
作者头像
林小帅
修改2019-09-10 17:13:18
2.6K0
修改2019-09-10 17:13:18
举报

在布局 Widget 中 Row、Column、ListBody、ListView、Wrap、Flow 等都是用于整个页面布局的 Widget,因为这些都支持存在多个子元素,较 html 语言来说,它严格规定了哪些 Widget 是可以存在多个子元素哪些 Widget 是只支持单个子元素。

在Flutter 的实际使用中 Row、Column、ListView 这三者都是使用频率较高的布局 Widget 。

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

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

01 - “轴”的概念

Flutter 中 Row、Column 与其他语言相较不同的是使用了 Axis “轴”的概念。在这一点上和 CSS flex 有点相似。这里 Row、Column 也继承了 Flex ,在一定程度上还是借鉴了 CSS 的实现。

Row、Column 继承关系
Row、Column 继承关系

怎么说呢?就是说 Row 我们都会认为是行 Column 我们会认为是列,在这点上没有异议。但在这里加入了 Main Axis(主轴)、CrossAxis(交叉轴) 的概念。

这是什么意思呢?就是说当前 Widget 渲染如果是横向的,那么它的主轴就是横向的,则交叉轴就是纵向的。渲染如果是纵向的那么它的主轴就是纵向的,则交叉轴就是横向的。

这时候你可能一脸 ???

没关系那我们用传统一点的 x、y 来转换一下:

渲染 Row 是行,它是横向的,那么它的主轴是 x 轴,交叉轴是 y 轴。

渲染 Column 是列,它是纵向的,那么它的主轴是 y 轴,交叉轴是 x 轴。

这样来说明的话应该可以理解了吧?

什么?你说还不明白?我的天呐,怎么会有这样的人?既然这样的话那就别怪我放大招了!来人呐!给我上图!

Row、Column 轴关系
Row、Column 轴关系

这样应该理解了吧,如果这样还没理解的话,那么……

这里虽然 Cross Axis 是翻译为“交叉轴”,但我个人更喜欢称之为“副轴”,因为这样在理解上会相对清晰很多。当然,这是个人习惯问题,少侠们亦可按官方翻译所理解。

02 - 构成属性

在理解完后“轴”的概念后,我们就可以看一看它的构成属性。

Row 属性构成
Row 属性构成
Column 属性构成
Column 属性构成

在源码中可以看到 Row、Column 拥有以上属性,这些属性均继承自 Flex 。这些属性大多为 enum 枚举类型,也就是说只要通过 “.” 调用获取有限的不可更改的数据列表的值就Ok,免去了输入字符串可能导致的字符不匹配的问题。

// 主轴的对齐方式
MainAxisAlignment mainAxisAlignment
// 交叉(副)轴的对齐方式
CrossAxisAlignment crossAxisAlignment
// 主轴方向的大小,即占有空间
MainAxisSize mainAxisSize
// 垂直方向 - 默认向下
VerticalDirection verticalDirection
// 文字方向 - 一般默认
TextDirection textDirection
// 文字基线
TextBaseline textBaseline
// 子元素列表,类型为 Widget
List<Widget> children

简单了解了基本属性之后,那么就来说说主要影响布局结构的 3 个属性:

  • mainAxisAlignment
  • crossAxisAlignment
  • mainAxisSize

mainAxisAlignment

mainAxisAlignment 是主轴的对齐方式,其中 Row 的主轴为 x 轴,Column 的主轴为 y 轴。

在我探索 mainAxisAlignment 对齐方式的最终渲染结果的时候,我发现其实可以将它分为两种对齐方式会更好,一种是轴线对齐方式,一种是空间分配对齐方式。

轴线对齐方式就是以主轴线为基础进行的平移对齐。

空间分配对齐方式就是以轴线为基础对轴上空间进行分配的对齐方式。

轴线对齐方式

  • start 默认值,即 Row 主轴上左对齐,Column 主轴上顶部对齐
  • end 即 Row 主轴上右对齐,Column 主轴上底部对齐
  • center 即 Row 主轴上水平居中对齐,Column 主轴上垂直居中对齐
轴线对齐方式(点击查看大图)
轴线对齐方式(点击查看大图)

空间分配对齐方式

  • spaceBetween 左右两极对齐,剩余元素以相同间隔平均分配剩余空间
  • spaceAround 每个元素以相同的左右间隔平均分配剩余空间
  • spaceEvenly 所有元素以相同的间隔平均分配剩余空间
空间分配对齐方式(点击查看大图)
空间分配对齐方式(点击查看大图)

crossAxisAlignment

mainAxisAlignment 是交叉轴的对齐方式,我称之为副轴,其中 Row 的交叉(副)轴为 y 轴,Column 的交叉(副)轴为 x 轴。

  • start 即 Row 交叉(副)轴的顶部对齐,Column 交叉(副)轴的左对齐
  • end 即 Row 交叉(副)轴的底部对齐,Column 交叉(副)轴的右对齐
  • center 默认值,即 Row 交叉(副)轴的垂直居中对齐,Column 交叉(副)轴的水平居中对齐
  • stretch 将 Row 子元素拉伸至交叉(副)轴高度相同,Column 子元素拉伸至交叉(副)轴宽度相同
  • baseline 需要与 TextBaseline 配合使用

不出意外,在交叉(副)轴上 start、end、center 的渲染表现还是符合预期的。

mainAxisAlignment 对齐方式(点击查看大图)
mainAxisAlignment 对齐方式(点击查看大图)

stretch 就是以交叉(副)轴为基础,将交叉(副)轴上的子元素拉伸至与交叉(副)轴所占空间相同,但又不影响主轴方向的空间。

以上就是影响主轴、交叉(副)轴最终渲染视图时的主要属性了。

mainAxisSize

mainAxisSize 也是比较简单的属性,从名字上来看就可以知道大概结果,主轴大小,意思就是这个属性控制着在 Row、Column 主轴方向上的大小。

它有两个值 max、min,默认值为 max。max 就是在主轴上大小为 100%,而 min 就是子元素所需最小空间,此时主轴上的对齐方式就看不出效果了。

verticalDirection

接下来就要说说会影响垂直方向行为的属性 verticalDirection,在源码中对于 verticalDirection 部分的说明

意思就是说 verticalDirection 属性会影响垂直方向的渲染行为,也就是会改变垂直方向的对齐方式。

verticalDirection 垂直的排列方向,它有两个值 up、down,默认值为 down。

用代码作为参考来看:

它只影响垂直方向的行为,对水平方向并无影响,即是影响 Row 的交叉(副)轴和 Column 的主轴。

textDirection 这个就不用详细说明了,就是文字书写方向。

textBaseline

关于 textBaseline 属性,很抱歉!尝试了多种与文字设定的方式配合后,依然没有在最后渲染的视图上表现出来 alphabetic、ideographic 两个值的差异。

03 - 案例实现

那我们就来实现一下 Flutter 中文网中给出的例子

【在Flutter中构建布局】

https://flutterchina.club/tutorials/layout/

可以看出它将设计图拆分为基本的元素,它分为4部分:一张图片,标题+按钮,功能按钮组以及文本块。

那我们就要考虑找出它最大的包裹元素,所以这里是 1 列 4 行。因为是从上到下所以这里用 Column 先确定列,再使用 4 个子元素实现行内容。

因为 Flutter 中文网已给出代码,所以这里就不详细说明实现步骤。具体代码可以参考:

【在Flutter中构建布局】

https://flutterchina.club/tutorials/layout/

或者

配合文章一同食用的代码 Github 地址:

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

问题:假设在不考虑功能的情况下使用 Row 和 Column 来完成如下布局,你会如何考虑和设计?

结语

Flutter布局机制的核心就是 widget。在Flutter中,几乎所有东西都是一个 widget - 甚至布局模型都是 widget。其实在使用起来和 html 的标签逻辑还是大部分相似的,只不过这里将这些 widget 设计得更细,每个 widget 都负责固定的渲染结果或行为模式。只要能够理解这些 widget 那么视图布局还是比较容易实现的。

最后总结:

  • 对于布局来说,难点不在于多复杂,而是在于你如何去理解拆分它。
  • 多思考学一种新语言和你所学过的语言有那些相似或者不同之处,对于相似之处可以快速理解,不同之处可以针对性理解。

参考来源:

Github 项目: https://github.com/linxsbox/myapp.git 在Flutter中构建布局: https://flutterchina.club/tutorials/layout/

相关文章

感谢大家的喜欢!

欢迎 关注、留言、分享、转发、在看。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档