鸿蒙开发(29)弹性布局 (Flex)

devtools/2025/1/12 10:00:47/

概述

弹性布局(Flex)提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间。常用于页面头部导航栏的均匀分布、页面框架的搭建、多行数据的排列等。

容器默认存在主轴与交叉轴,子元素默认沿主轴排列,子元素在主轴方向的尺寸称为主轴尺寸,在交叉轴方向的尺寸称为交叉轴尺寸。
图1 主轴为水平方向的Flex容器示意图
在这里插入图片描述

基本概念

  • 主轴:Flex组件布局方向的轴线,子元素默认沿着主轴排列。主轴开始的位置称为主轴起始点,结束位置称为主轴结束点。

  • 交叉轴:垂直于主轴方向的轴线。交叉轴开始的位置称为交叉轴起始点,结束位置称为交叉轴结束点。

布局方向

在弹性布局中,容器的子元素可以按照任意方向排列。通过设置参数direction,可以决定主轴的方向,从而控制子元素的排列方向。
在这里插入图片描述

FlexDirection.Row(默认值):主轴为水平方向,子元素从起始端沿着水平方向开始排布

typescript">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相反的方向开始排布。

typescript">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:主轴为垂直方向,子元素从起始端沿着垂直方向开始排布。

typescript">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相反的方向开始排布。

typescript">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)

在这里插入图片描述

布局换行

弹性布局分为单行布局和多行布局。默认情况下,Flex容器中的子元素都排在一条线(又称“轴线”)上。wrap属性控制当子元素主轴尺寸之和大于容器主轴尺寸时,Flex是单行布局还是多行布局。在多行布局时,通过交叉轴方向,确认新行排列方向。

FlexWrap. NoWrap(默认值):不换行。如果子元素的宽度总和大于父元素的宽度,则子元素会被压缩宽度。

typescript">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:换行,每一行子元素按照主轴方向排列。

typescript">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:换行,每一行子元素按照主轴反方向排列。

typescript">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)

在这里插入图片描述

主轴对齐方式

通过justifyContent参数设置子元素在主轴方向的对齐方式。
在这里插入图片描述

FlexAlign.Start(默认值):子元素在主轴方向起始端对齐, 第一个子元素与父元素边沿对齐,其他元素与前一个元素对齐

typescript">let PTopBottom:Record<string,number> = { 'top': 10, 'bottom': 10 }
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(PTopBottom)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

FlexAlign.Center:子元素在主轴方向居中对齐。

typescript">let PTopBottom:Record<string,number> = { 'top': 10, 'bottom': 10 }
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(PTopBottom)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

FlexAlign.End:子元素在主轴方向终点端对齐, 最后一个子元素与父元素边沿对齐,其他元素与后一个元素对齐。

typescript">let PTopBottom:Record<string,number> = { 'top': 10, 'bottom': 10 }
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(PTopBottom)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

FlexAlign.SpaceBetween:Flex主轴方向均匀分配弹性元素,相邻子元素之间距离相同。第一个子元素和最后一个子元素与父元素边沿对齐。

typescript">let PTopBottom1:Record<string,number> = { 'top': 10, 'bottom': 10 }
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(PTopBottom1)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

FlexAlign.SpaceAround:Flex主轴方向均匀分配弹性元素,相邻子元素之间距离相同。第一个子元素到主轴起始端的距离和最后一个子元素到主轴终点端的距离是相邻元素之间距离的一半。

typescript">let PTopBottom:Record<string,number> = { 'top': 10, 'bottom': 10 }
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(PTopBottom)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

FlexAlign.SpaceEvenly:Flex主轴方向元素等间距布局,相邻子元素之间的间距、第一个子元素与主轴起始端的间距、最后一个子元素到主轴终点端的间距均相等。

typescript">let PTopBottom:Record<string,number> = { 'top': 10, 'bottom': 10 }
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(PTopBottom)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

交叉轴对齐方式

容器和子元素都可以设置交叉轴对齐方式,且子元素设置的对齐方式优先级较高。

容器组件设置交叉轴对齐

可以通过Flex组件的alignItems参数设置子元素在交叉轴的对齐方式。

ItemAlign.Auto:使用Flex容器中默认配置。

typescript">let SWh:Record<string,number|string> = { 'width': '90%', 'height': 80 }
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(SWh)
.padding(10)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

ItemAlign.Start:交叉轴方向首部对齐。

typescript">let SWh:Record<string,number|string> = { 'width': '90%', 'height': 80 }
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(SWh)
.padding(10)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

ItemAlign.Center:交叉轴方向居中对齐。

typescript">let SWh:Record<string,number|string> = { 'width': '90%', 'height': 80 }
Flex({ alignItems: ItemAlign.Center }) {  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(SWh)
.padding(10)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

ItemAlign.End:交叉轴方向底部对齐。

typescript">let SWh:Record<string,number|string> = { 'width': '90%', 'height': 80 }
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(SWh)
.padding(10)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

ItemAlign.Stretch:交叉轴方向拉伸填充,在未设置尺寸时,拉伸到容器尺寸。

typescript">let SWh:Record<string,number|string> = { 'width': '90%', 'height': 80 }
Flex({ alignItems: ItemAlign.Stretch }) {  Text('1').width('33%').backgroundColor(0xF5DEB3)  Text('2').width('33%').backgroundColor(0xD2B48C)  Text('3').width('33%').backgroundColor(0xF5DEB3)
}
.size(SWh)
.padding(10)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

ItemAlign. Baseline:交叉轴方向文本基线对齐。

typescript">let SWh:Record<string,number|string> = { 'width': '90%', 'height': 80 }
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(SWh)
.padding(10)
.backgroundColor(0xAFEEEE)

在这里插入图片描述

子元素设置交叉轴对齐

子元素的alignSelf属性也可以设置子元素在父容器交叉轴的对齐格式,且会覆盖Flex布局容器中alignItems配置。如下例所示:

typescript">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的定义。

内容对齐

可以通过alignContent参数设置子元素各行在交叉轴剩余空间内的对齐方式,只在多行的Flex布局中生效,可选值有:

FlexAlign.Start:子元素各行与交叉轴起点对齐。

typescript">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:子元素各行在交叉轴方向居中对齐。

typescript">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:子元素各行与交叉轴终点对齐。

typescript">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:子元素各行与交叉轴两端对齐,各行间垂直间距平均分布。

typescript">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:子元素各行间距相等,是元素首尾行与交叉轴两端距离的两倍。

typescript">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: 子元素各行间距,子元素首尾行与交叉轴两端距离都相等。

typescript">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)          

在这里插入图片描述

自适应拉伸

在弹性布局父组件尺寸过小时,通过子元素的以下属性设置其在父容器的占比,达到自适应布局。

flexBasis:设置子元素在父容器主轴方向上的基准尺寸。如果设置了该属性,则子项占用的空间为该属性所设置的值;如果没设置该属性,那子项的空间为width/height的值。

typescript">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.flexBasis(100)  .height(100).backgroundColor(0xF5DEB3)Text('flexBasis(100)').flexBasis(100).width(200) // flexBasis值为100,覆盖width的设置值,宽度为100vp.height(100).backgroundColor(0xD2B48C)
}.width('90%').height(120).padding(10).backgroundColor(0xAFEEEE)

在这里插入图片描述

flexGrow:设置父容器的剩余空间分配给此属性所在组件的比例。用于分配父组件的剩余空间。

typescript">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: 当父容器空间不足时,子元素的压缩比例。

typescript">Flex({ direction: FlexDirection.Row }) {Text('flexShrink(3)').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) 

在这里插入图片描述

场景示例

使用弹性布局,可以实现子元素沿水平方向排列,两端对齐,子元素间距平分,垂直方向上子元素居中的效果。

typescript">@Entry  
@Component
struct FlexExample {build() {Column() {Column({ space: 5 }) {Flex({ direction: FlexDirection.Row, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {Text('1').width('30%').height(50).backgroundColor(0xF5DEB3)Text('2').width('30%').height(50).backgroundColor(0xD2B48C)Text('3').width('30%').height(50).backgroundColor(0xF5DEB3)}.height(70).width('90%').backgroundColor(0xAFEEEE)}.width('100%').margin({ top: 5 })}.width('100%') }
}

在这里插入图片描述

文档:弹性布局 (Flex)


http://www.ppmy.cn/devtools/149573.html

相关文章

碰一碰发视频的剪辑功能开发的细节源码搭建,支持OEM

在短视频盛行的今天&#xff0c;为碰一碰发视频增添剪辑功能&#xff0c;能极大提升用户创作的灵活性与趣味性。下面将详细阐述这一功能从技术选型到源码搭建的全过程。 一、技术选型 前端 框架&#xff1a;选择 React 作为前端框架&#xff0c;其基于组件化的开发模式&#x…

基于SpringBoot的洗浴管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

不同音频振幅dBFS计算方法

1. 振幅的基本概念 振幅是描述音频信号强度的一个重要参数。它通常表示为信号的幅度值&#xff0c;幅度越大&#xff0c;声音听起来就越响。为了更好地理解和处理音频信号&#xff0c;通常会将振幅转换为分贝&#xff08;dB&#xff09;单位。分贝是一个对数单位&#xff0c;能…

数据库系统原理期末

第一章概述 文章目录 第一章概述1. 数据库概述2. 数据库相关概念3. 数据库系统 DBS4. 外模式/模式映像5. 模式/内模式映像6. 数据独立性 第二章关系数据库1. 关系模型2. 码&#xff08;Key&#xff09;3. 关系模型三要素4. 关系代数 第三章结构化查询语言 SQL1. 视图&#xff0…

Elasticsearch:优化的标量量化 - 更好的二进制量化

作者&#xff1a;来自 Elastic Benjamin Trent 在这里&#xff0c;我们解释了 Elasticsearch 中的优化标量量化以及如何使用它来改进更好的二进制量化 (Better Binary Quantization - BBQ)。 我们的全新改进版二进制量化 (Better Binary Quantization - BBQ) 索引现在变得更强大…

Java阶段四04

第4章-第4节 一、知识点 CSRF、token、JWT 二、目标 理解什么是CSRF攻击以及如何防范 理解什么是token 理解什么是JWT 理解session验证和JWT验证的区别 学会使用JWT 三、内容分析 重点 理解什么是CSRF攻击以及如何防范 理解什么是token 理解什么是JWT 理解session验…

Nacos server 2.4.0 版本已知问题和 Bug 汇总

Nacos server 2.4.0 版本已知问题和 Bug 汇总 核心功能问题 集群模式下的数据一致性问题 在特定条件下&#xff0c;可能出现节点间数据同步延迟某些情况下会出现脑裂现象Issue #9876: 数据同步时可能出现死锁 内存泄漏问题 长时间运行后可能出现内存泄漏当配置变更频繁时&…

【Rust自学】11.4. 用should_panic检查恐慌

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.4.1. 验证错误处理的情况 测试函数出了验证代码的返回值是否正确&#xff0c;还需要验证代码是否如预期的去处理了发生错误的情况。比…