ArkTs布局入门02——弹性布局(Flex)
1、概述
弹性布局(Flex)提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间。容器默认存在主轴与交叉轴,子元素默认沿主轴排列,子元素在主轴方向的尺寸称为主轴尺寸,在交叉轴方向的尺寸称为交叉轴尺寸。弹性布局在开发场景中用例特别多,比如页面头部导航栏的均匀分布、页面框架的搭建、多行数据的排列等等。
主轴为水平方向的Flex容器示意图
2、基本概念
主轴:Flex组件布局方向的轴线,子元素默认沿着主轴排列。主轴开始的位置称为主轴起始点,结束位置称为主轴结束点。
交叉轴:垂直于主轴方向的轴线。交叉轴开始的位置称为交叉轴起始点,结束位置称为交叉轴结束点。
3、布局方向
在弹性布局中,容器的子元素可以按照任意方向排列。通过设置参数direction,可以决定主轴的方向,从而控制子组件的排列方向。
弹性布局方向图
- FlexDirection.Row(默认值):主轴为水平方向,子组件从起始端沿着水平方向开始排布
Flex({ direction: FlexDirection.Row }) {
Text('1').width('33%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(50).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
- FlexDirection.RowReverse:主轴为水平方向,子组件从终点端沿着FlexDirection. Row相反的方向开始排布
Flex({ direction: FlexDirection.RowReverse }) {
Text('1').width('33%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(50).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
- FlexDirection.Column:主轴为垂直方向,子组件从起始端沿着垂直方向开始排布
Flex({ direction: FlexDirection.Column }) {
Text('1').width('100%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('100%').height(50).backgroundColor(0xD2B48C)
Text('3').width('100%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
- FlexDirection.ColumnReverse:主轴为垂直方向,子组件从终点端沿着FlexDirection. Column相反的方向开始排布
Flex({ direction: FlexDirection.ColumnReverse }) {
Text('1').width('100%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('100%').height(50).backgroundColor(0xD2B48C)
Text('3').width('100%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
4、布局换行
弹性布局分为单行布局和多行布局。默认情况下,Flex容器中的子元素都排在一条线(又称“轴线”)上。wrap参数控制当子元素主轴尺寸之和大于容器主轴尺寸时,Flex是单行布局还是多行布局。在多行布局时,通过交叉轴方向,确认新行堆叠方向。
- FlexWrap. NoWrap(默认值):不换行。如果子组件的宽度总和大于父元素的宽度,则子组件会被压缩宽度
Flex({ wrap: FlexWrap.NoWrap }) {
Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
Text('3').width('50%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
- FlexWrap. Wrap:换行,每一行子组件按照主轴方向排列
Flex({ wrap: FlexWrap.Wrap }) {
Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
Text('3').width('50%').height(50).backgroundColor(0xD2B48C)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
- FlexWrap. WrapReverse:换行,每一行子组件按照主轴反方向排列。
Flex({ wrap: FlexWrap.WrapReverse}) {
Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
Text('3').width('50%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)
5、主轴对齐方式
通过justifyContent参数设置在主轴方向的对齐方式。
- FlexAlign.Start(默认值):子组件在主轴方向起始端对齐, 第一个子组件与父元素边沿对齐,其他元素与前一个元素对齐
Flex({ justifyContent: FlexAlign.Start }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)
- FlexAlign.Center:子组件在主轴方向居中对齐。
Flex({ justifyContent: FlexAlign.Center }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)
- FlexAlign.End:子组件在主轴方向终点端对齐, 最后一个子组件与父元素边沿对齐,其他元素与后一个元素对齐
Flex({ justifyContent: FlexAlign.End }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)
- FlexAlign.SpaceBetween:Flex主轴方向均匀分配弹性元素,相邻子组件之间距离相同。第一个子组件和最后一个子组件与父元素边沿对齐
Flex({ justifyContent: FlexAlign.SpaceBetween }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)
- FlexAlign.SpaceAround:Flex主轴方向均匀分配弹性元素,相邻子组件之间距离相同。第一个子组件到主轴起始端的距离和最后一个子组件到主轴终点端的距离是相邻元素之间距离的一半
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)
- FlexAlign.SpaceEvenly:Flex主轴方向元素等间距布局,相邻子组件之间的间距、第一个子组件与主轴起始端的间距、最后一个子组件到主轴终点端的间距均相等
Flex({ justifyContent: FlexAlign.SpaceEvenly }) {
Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
Text('2').width('20%').height(50).backgroundColor(0xD2B48C)
Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)
6、交叉轴对齐方式
容器和子元素都可以设置交叉轴对齐方式,且子元素设置的对齐方式优先级较高
6.1、容器组件设置交叉轴对齐
可以通过Flex组件的alignItems参数设置子组件在交叉轴的对齐方式。
- ItemAlign.Auto:使用Flex容器中默认配置
Flex({ alignItems: ItemAlign.Auto }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)
- ItemAlign.Start:交叉轴方向首部对齐。
Flex({ alignItems: ItemAlign.Start }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)
- ItemAlign.End:交叉轴方向底部对齐
Flex({ alignItems: ItemAlign.End }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)
- ItemAlign.Stretch:交叉轴方向拉伸填充,在未设置尺寸时,拉伸到容器尺寸
Flex({ alignItems: ItemAlign.Stretch }) {
Text('1').width('33%').backgroundColor(0xF5DEB3)
Text('2').width('33%').backgroundColor(0xD2B48C)
Text('3').width('33%').backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)
- ItemAlign. Baseline:交叉轴方向文本基线对齐
Flex({ alignItems: ItemAlign.Baseline }) {
Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)
Text('2').width('33%').height(40).backgroundColor(0xD2B48C)
Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)
6.2、子组件设置交叉轴对齐
子组件的alignSelf属性也可以设置子组件在父容器交叉轴的对齐格式,且会覆盖Flex布局容器中alignItems配置。
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { // 容器组件设置子组件居中
Text('alignSelf Start').width('25%').height(80)
.alignSelf(ItemAlign.Start)
.backgroundColor(0xF5DEB3)
Text('alignSelf Baseline')
.alignSelf(ItemAlign.Baseline)
.width('25%')
.height(80)
.backgroundColor(0xD2B48C)
Text('alignSelf Baseline').width('25%').height(100)
.backgroundColor(0xF5DEB3)
.alignSelf(ItemAlign.Baseline)
Text('no alignSelf').width('25%').height(100)
.backgroundColor(0xD2B48C)
Text('no alignSelf').width('25%').height(100)
.backgroundColor(0xF5DEB3)
}.width('90%').height(220).backgroundColor(0xAFEEEE)
上例中,Flex容器中alignItems设置交叉轴子组件的对齐方式为居中,子组件自身设置了alignSelf属性的情况,覆盖父组件的alignItems值,表现为alignSelf的定义。
6.3、内容对齐
可以通过alignContent参数设置子组件各行在交叉轴剩余空间内的对齐方式,只在多行的flex布局中生效,可选值有:
- FlexAlign.Start:子组件各行与交叉轴起点对齐
Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.Start }) {
Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)
- FlexAlign.Center:子组件各行在交叉轴方向居中对齐
Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.Center }) {
Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)
- FlexAlign.End:子组件各行与交叉轴终点对齐。
Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.End }) {
Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)
- FlexAlign.SpaceBetween:子组件各行与交叉轴两端对齐,各行间垂直间距平均分布
Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.SpaceBetween }) {
Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)
- FlexAlign.SpaceAround:子组件各行间距相等,是元素首尾行与交叉轴两端距离的两倍
Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.SpaceAround }) {
Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)
- FlexAlign.SpaceEvenly: 子组件各行间距,子组件首尾行与交叉轴两端距离都相等
Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.SpaceEvenly }) {
Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)
7、自适应拉伸
在弹性布局父组件尺寸不够大的时候,通过子组件的下面几个属性设置其在父容器的占比,达到自适应布局能力。
- flexBasis:设置子组件在父容器主轴方向上的基准尺寸。如果设置了该值,则子项占用的空间为设置的值;如果没设置该属性,那子项的空间为width/height的值
Flex() {
Text('flexBasis("auto")')
.flexBasis('auto') // 未设置width以及flexBasis值为auto,内容自身宽度
.height(100)
.backgroundColor(0xF5DEB3)
Text('flexBasis("auto")' + ' width("40%")')
.width('40%')
.flexBasis('auto') //设置width以及flexBasis值auto,使用width的值
.height(100)
.backgroundColor(0xD2B48C)
Text('flexBasis(100)') // 未设置width以及flexBasis值为100,宽度为100vp
.fontSize(15)
.flexBasis(100)
.height(100)
.backgroundColor(0xF5DEB3)
Text('flexBasis(100)')
.fontSize(15)
.flexBasis(100)
.width(200) // flexBasis值为100,覆盖width的设置值,宽度为100vp
.height(100)
.backgroundColor(0xD2B48C)
}.width('90%').height(120).padding(10).backgroundColor(0xAFEEEE)
- flexGrow:设置父容器的剩余空间分配给此属性所在组件的比例。用于“瓜分”父组件的剩余空间
Flex() {
Text('flexGrow(2)')
.flexGrow(2)
.width(100)
.height(100)
.backgroundColor(0xF5DEB3)
Text('flexGrow(3)')
.flexGrow(3)
.width(100)
.height(100)
.backgroundColor(0xD2B48C)
Text('no flexGrow')
.width(100)
.height(100)
.backgroundColor(0xF5DEB3)
}.width(420).height(120).padding(10).backgroundColor(0xAFEEEE)
父容器宽度420vp,三个子元素原始宽度为100vp,左右padding为20vp,总和320vp,剩余空间100vp根据flexGrow值的占比分配给子元素,未设置flexGrow的子元素不参与“瓜分”。
第一个元素以及第二个元素以2:3分配剩下的100vp。第一个元素为100vp+100vp*2/5=140vp,第二个元素为100vp+100vp*3/5=160vp。
- flexShrink: 当父容器空间不足时,子组件的压缩比例
Flex({ direction: FlexDirection.Row }) {
Text('flexShrink(3)')
.fontSize(15)
.flexShrink(3)
.width(200)
.height(100)
.backgroundColor(0xF5DEB3)
Text('no flexShrink')
.width(200)
.height(100)
.backgroundColor(0xD2B48C)
Text('flexShrink(2)')
.flexShrink(2)
.width(200)
.height(100)
.backgroundColor(0xF5DEB3)
}.width(400).height(120).padding(10).backgroundColor(0xAFEEEE)
8、结语
弹性布局是仅次于线性布局的一种高频使用布局,未来在很多demo中都将会见到他的身影。
接下来,我们将介绍剩下的其他布局,请持续关注“ArkTs布局入门03”
如果你对鸿蒙开发感兴趣,加入“Harmony自习室”!
ArkTs布局入门02——弹性布局(Flex)的更多相关文章
- 前端入门5-CSS弹性布局flex
本篇文章已授权微信公众号 dasu_Android(大苏)独家发布 声明 本系列文章内容全部梳理自以下四个来源: <HTML5权威指南> <JavaScript权威指南> MD ...
- display:flex 布局教程,弹性布局!
display:flex 布局教程 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现. ...
- 响应式布局(CSS3弹性盒flex布局模型)
传统的布局方式都是基于盒模型的 利用display.position.float来布局有一定局限性 比如说实现自适应垂直居中 随着响应式布局的流行,CSS3引入了更加灵活的弹性布局模型 flex弹性布 ...
- React Native 弹性布局FlexBox
React Native采用一中全新的布局方式:FlexBox(弹性布局).可以很方便的实现各种复杂布局,是全新的针对web和移动开发布局的一种实现方式. 何为FlexBox? 完整名称为:the f ...
- 【repost】CSS3弹性布局
本文导读:在CSS 3中,CSS Flexible Box模块为一个非常重要的模块,该模块用于以非常灵活的方式实现页面布局处理.使用CSS Flexible Box模块中定义的弹性盒布局技术,可以根据 ...
- Android 弹性布局 FlexboxLayout了解一下
原文链接:https://mp.weixin.qq.com/s/Mi3cK7xujmEMI_rc51-r4g RelativeLayout.LinearLayout等常用布局相信大家早已耳熟能详,今天 ...
- HTML/css之弹性布局
1.flex 弹性布局 产生的比较晚 目前在移动网页开发中可以使用 而且逐渐成为主流. 在桌面网页开发中,使用的比较少 (主要是桌面浏览器的兼容性问题更加严重) 开启方法: 在容器标签上,加上disp ...
- CCS3的过渡、变换、动画以及响应式布局、弹性布局
CSS3 过渡 .变换.动画 在没有CSS3之前,如果页面上需要一些动画效果,要么你自己编写 JavaScript,要么使用 JavaScript 框架(如 jQuery)来提高效率. 但是CSS3出 ...
- flex弹性布局学习笔记
前言 资料来源于网络,本人只是对此作了一下操作,记录于此以便以后查阅.目的在于梳理自己前端凌乱的知识点. 本文根据 Brian Franco 的一个flexbox.scss库来记录 入职新公司前对移动 ...
- flex弹性布局
Flex 布局教程:语法篇 原文地址:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool 作者: ...
随机推荐
- freemarker实现导出word复选框可点击效果
记一次java导出word文档,导出的word文档里包含复选框并且能点击,一开始做了个输出字符的,比如这样: □,然而并不能满足需求,网上找了一大堆也都是这种的. 正文开始: 先在word中添加复选框 ...
- K8S基本组件梳理
Master组件 apiserver:对资源对象进行curd操作,例如pod和server:将所有的状态储存到etcd中. schedule:监控未调度的pod,根据pod的资源需求.资源可用性和其他 ...
- 【VMware VCF】使用 PowerVCF 连接和管理 VMware Cloud Foundation 环境。
VMware 有一个非常强大的命令行工具叫 PowerCLI,该工具是基于 PowerShell 开发的模块,主要用于在 Windows 环境中连接和管理传统虚拟化解决方案,比如 vSphere.vS ...
- foobar2000 v2.1.2 汉化版(更新日期: 2024.02.27)
新春佳节,送上一份新年礼物,祝您在新的一年里,万事如意,心想事成,身体健康,事业有成,财源广进,家庭和睦,笑容常开,好运连连. foobar2000 v2.1.2 汉化版 ---------- ...
- 墨天轮访谈 | SelectDB 衣国垒:Apache Doris(incubating)1.0版本特性解析与未来规划
分享嘉宾:衣国垒 Apache Doris Committer.SelectDB 联合创始人&CTO 整理:墨天轮社区 导读 大家好,我是来自Apache Doris社区的衣国垒,也是Sele ...
- 57.dom递归退出循环的时机
递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是return:返回终止递归. 终止的条件: 1.判断递归的次数是否达到某一限定值 2.判断运算 ...
- 0602-nn.Module
0602-nn.Module 目录 一.nn.Module 1.1 构建一层网络--全连接层 1.2 构建多层网络--多层感知机 pytorch完整教程目录:https://www.cnblogs.c ...
- day15-三大基本结构
顺序结构 Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行. 顺序结构是最简单的算法结构. 语句和语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组 ...
- 为什么说Kafka还不是完美的实时数据通道
本文主要谈谈Kafka用于实时数据通道场景的缺陷,以及如何在架构上进行弥补. Kafka归属于消息队列类产品,其他竞品还有RabbitMQ.RocketMQ等,总的来说它们都是基于生产者.中介和消费者 ...
- Iterator和Iterable
Java遍历List有三种方式 public static void main(String[] args) { List<String> list = new ArrayList< ...