文章目录
- 每日一句正能量
- 引言
- 一、ArkUI 布局系统架构:理解渲染管线
- 二、线性布局:Column 与 Row
- 2.1 核心属性
- 2.2 代码示例:设置列表项
- 2.3 自适应拉伸:layoutWeight 与 Blank
- 三、弹性布局:Flex
- 3.1 核心参数
- 3.2 子组件弹性属性
- 3.3 Flex 与 Column/Row 的选型策略
- 四、层叠布局:Stack
- 4.1 定位方式
- 4.2 典型应用场景
- 五、网格布局:Grid
- 5.1 基础用法
- 5.2 跨列与跨行
- 六、响应式与自适应布局
- 6.1 栅格断点规则
- 6.2 GridContainer 与 useSizeType
- 七、布局性能优化实践
- 八、总结
每日一句正能量
“不经思考的行动,到头来只会是无用功。”
没有经过倾听、观察、思考的匆忙行动,往往偏离目标或重复错误。行动之前要先“听见”事实与反馈,否则再努力也是徒劳。
向内建立清晰的边界与自省,再向外选择对的人与事,以倾听和包容为方法,最终达到不费力却深刻的默契与从容。
引言
在 HarmonyOS 应用开发中,UI 界面不仅是视觉的呈现,更是用户与系统交互的桥梁。ArkTS 作为 HarmonyOS 主推的声明式开发语言,其布局系统经历了从传统命令式到现代声明式的范式革命。与早期需要开发者手动计算坐标、逐像素调整位置的命令式布局不同,ArkTS 的布局系统通过组合式 API 让开发者以更接近自然语义的方式描述界面结构,框架自动完成测量、布局与绘制。
本文将系统梳理 ArkTS 布局体系的核心容器与机制,涵盖线性布局、弹性布局、层叠布局、网格布局及响应式适配方案,并结合实际代码示例与性能优化策略,帮助开发者建立完整的布局思维模型。
一、ArkUI 布局系统架构:理解渲染管线
在深入具体布局容器之前,有必要先理解 ArkUI 布局引擎的工作流程。一个组件最终能显示在屏幕的哪个位置,通常会经历三个阶段:
1. 测量阶段(Measure Pass)
父组件向子组件传递可用空间和尺寸约束,子组件根据内容、显式尺寸与约束计算自身大小。例如,当父容器宽度为400vp,子组件设置了width('50%'),则其实际测量宽度为200vp。
2. 布局阶段(Layout Pass)
父组件按照自身的布局规则,结合子组件的测量结果,确定每个子组件在容器内的最终坐标位置。这一阶段决定了组件的x、y偏移量。
3. 绘制阶段(Draw Pass)
将布局结果渲染到屏幕,生成具体的渲染指令,处理背景、边框、阴影和内容绘制。
ArkUI 3.0 之后引入了增量布局机制,仅重新计算发生变更的部分,而非整棵树重排。同时支持AsyncMeasure异步测量,优化复杂嵌套场景下的布局性能。声明式语法使得开发者只需描述 UI 应该「长什么样」,而无需关心「怎么画」,框架内部通过 Diff 算法直接基于 RENDER 树节点比较差异,实现渲染算法树三合一,界面滑动加载速度较传统方案提升约 45%。
二、线性布局:Column 与 Row
线性布局是 ArkTS 中最基础、最常用的布局方式,通过Column和Row两个容器组件实现。
Column容器内子组件按照垂直方向依次排列,适用于纵向堆叠的场景,如表单、设置列表、卡片内容等。
Row容器内子组件按照水平方向依次排列,适用于横向排列的场景,如导航栏、工具栏、标签组等。
2.1 核心属性
| 属性 | 作用 | Column 取值 | Row 取值 |
|---|---|---|---|
space | 主轴方向子组件间距 | 数值 | 数值 |
justifyContent | 主轴对齐方式 | FlexAlign | FlexAlign |
alignItems | 交叉轴对齐方式 | HorizontalAlign | VerticalAlign |
2.2 代码示例:设置列表项
@Entry@Componentstruct SettingsPage{build(){Column({space:12}){// 标题栏Row(){Text('设置').fontSize(24).fontWeight(FontWeight.Bold)Blank()// 自动填充空白Image($r('app.media.close')).width(24).height(24)}.width('100%').padding(16)// 设置项列表Column({space:8}){this.buildSettingItem('Wi-Fi',true)this.buildSettingItem('蓝牙',false)this.buildSettingItem('通知',true)this.buildSettingItem('定位服务',false)}.width('100%').padding({left:16,right:16})}.width('100%').height('100%').backgroundColor('#F5F7FA')}@BuilderbuildSettingItem(label:string,isOn:boolean){Row(){Text(label).fontSize(16).fontColor('#333333')Blank()Toggle({type:ToggleType.Switch,isOn:isOn})}.width('100%').height(56).padding({left:16,right:16}).backgroundColor(Color.White).borderRadius(12)}}2.3 自适应拉伸:layoutWeight 与 Blank
在线性布局中,layoutWeight属性用于配置子组件在主轴方向上的尺寸权重。配置该属性后,子组件沿主轴方向的显式尺寸设置将失效,具体尺寸根据权重比例自动计算。Blank组件则是一个空白填充组件,在容器主轴方向自动填充剩余空间,常用于实现左右对齐的列表项布局。
三、弹性布局:Flex
弹性布局(Flex)的效果类似于线性布局,同样使子元素呈线性排列,但在子元素的排列、对齐和剩余空间分配等方面更加灵活。Flex 是 Web 开发者最熟悉的布局模型之一,ArkTS 完整复刻了 CSS Flexbox 的核心能力。
3.1 核心参数
| 参数 | 类型 | 说明 |
|---|---|---|
direction | FlexDirection | 主轴方向:Row / Column / RowReverse / ColumnReverse |
wrap | FlexWrap | 换行方式:NoWrap / Wrap / WrapReverse |
justifyContent | FlexAlign | 主轴对齐 |
alignItems | ItemAlign | 交叉轴对齐 |
alignContent | FlexAlign | 多行内容对齐(wrap 生效时) |
3.2 子组件弹性属性
Flex({direction:FlexDirection.Row,wrap:FlexWrap.Wrap}){Text('标签 A').width(80).height(40).backgroundColor('#FF9F43').flexGrow(1)// 空间充足时按比例扩展Text('标签 B').width(80).height(40).backgroundColor('#10AC84').flexGrow(2)// 分得更多剩余空间Text('标签 C').width(80).height(40).backgroundColor('#5F27CD').flexShrink(0)// 空间不足时不压缩}.width('100%').padding(12)3.3 Flex 与 Column/Row 的选型策略
Column/Row 适用于:简单线性排列、页面骨架结构、固定数量的子项、追求代码简洁和极致性能的场景。由于不支持换行,布局计算路径更短,渲染性能更优。
Flex 适用于:需要自动换行(wrap)、多行对齐(alignContent)、主轴方向动态切换、子项数量和大小不确定的流式内容场景。最佳实践是外层用 Column/Row 搭骨架,内层动态区域用 Flex 处理流式内容,两者分层协作。
四、层叠布局:Stack
层叠布局(Stack)用于在屏幕上预留一块区域来显示组件中的元素,提供元素可以重叠的布局能力。容器中的子元素依次入栈,后一个子元素覆盖前一个子元素,类似于 Photoshop 中的图层叠加。
4.1 定位方式
Stack 容器支持两种定位方式:
- 默认定位:子组件按添加顺序依次叠加,无偏移时中心对齐
- 绝对定位:通过
position({ x, y })或offset({ x, y })精确控制位置
4.2 典型应用场景
@Entry@Componentstruct StackDemo{build(){Stack({alignContent:Alignment.Center}){// 底层:背景图Image($r('app.media.cover')).width('100%').height(200).objectFit(ImageFit.Cover)// 中层:半透明遮罩Column().width('100%').height(200).backgroundColor('rgba(0,0,0,0.4)')// 顶层:文字内容Column(){Text('鸿蒙生态赋能').fontSize(24).fontColor(Color.White).fontWeight(FontWeight.Bold)Text('第五期技术实战').fontSize(14).fontColor('#DDDDDD').margin({top:8})}}.width('100%').height(200)}}层叠布局的典型应用场景包括:广告弹窗、卡片层叠效果、图片水印叠加、视频播放控制层叠加等。通过zIndex属性还可以手动控制层级顺序,数值越大越靠上。
五、网格布局:Grid
网格布局(Grid)是一种二维布局系统,支持将容器划分为若干行和列,子组件按照指定的行列位置进行放置。相比线性布局的一维排列,网格布局能更高效地实现复杂的卡片矩阵、相册网格、仪表盘等界面。
5.1 基础用法
@Entry@Componentstruct GridDemo{privateitems:string[]=['相册','相机','日历','时钟','天气','地图']build(){Grid(){ForEach(this.items,(item:string,index:number)=>{GridItem(){Column(){Image($r(`app.media.icon_${index}`)).width(48).height(48)Text(item).fontSize(14).margin({top:8})}.width('100%').height('100%').justifyContent(FlexAlign.Center)}.backgroundColor('#F5F7FA').borderRadius(16)})}.columnsTemplate('1fr 1fr 1fr')// 三列等宽.rowsTemplate('1fr 1fr')// 两行等高.columnsGap(12).rowsGap(12).padding(16).width('100%').height(400)}}5.2 跨列与跨行
通过columnStart、columnEnd、rowStart、rowEnd属性,子组件可以跨越多个网格单元格,实现类似「大图+小图」的复杂布局效果。
六、响应式与自适应布局
HarmonyOS 应用需要同时适配手机、平板、折叠屏、2in1 设备等多种形态,响应式布局是不可或缺的能力。ArkTS 提供了基于断点的栅格系统,以设备水平宽度(vp)作为断点依据。
6.1 栅格断点规则
| 设备宽度 | 类型 | 列数 | 间隔 | 边距 |
|---|---|---|---|---|
| 0 ~ 320vp | XS | 2 | 12vp | 12vp |
| 320 ~ 600vp | SM | 4 | 24vp | 24vp |
| 600 ~ 840vp | MD | 8 | 24vp | 32vp |
| ≥ 840vp | LG | 12 | 24vp | 48vp |
6.2 GridContainer 与 useSizeType
GridContainer(){Row(){Text('自适应卡片').useSizeType({xs:{span:2,offset:0},// 手机:占满2列sm:{span:2,offset:0},// 大屏手机:占2列md:{span:4,offset:0},// 平板:占4列lg:{span:6,offset:0},// 2in1:占6列})}}通过useSizeType属性,开发者可以为同一组件在不同断点下指定不同的列跨度(span)和偏移量(offset),实现真正的「一次开发,多端部署」。
七、布局性能优化实践
布局性能直接影响应用的流畅度和用户体验。以下是 ArkTS 布局优化的核心策略:
1. 减少布局层级嵌套
每增加一层嵌套,就会多一轮 Measure 和 Layout 计算。尽量扁平化组件树,能用单层 Flex 解决的不用嵌套 Column+Row。
2. 优先使用 Column/Row 而非 Flex
Column/Row 只处理一维线性排列,布局计算路径更短,渲染性能优于 Flex。仅在需要换行、多行对齐等 Flex 特有能力时才使用 Flex。
3. 避免在循环中创建复杂布局
对于长列表,使用LazyForEach替代ForEach,配合cachedCount预加载缓存项,避免一次性渲染全部子组件。
4. 合理使用固定尺寸
当组件内容尺寸确定时,优先使用固定数值(如width(200))而非百分比或自适应计算,可减少测量阶段的递归开销。
5. 利用freezeWhenInactive冻结不可见组件
对于不可见或离屏组件,启用freezeWhenInactive减少不必要的布局刷新和重绘。
List(){LazyForEach(this.dataSource,(item:Item)=>{ListItem(){ItemComponent({item:item})}.freezeWhenInactive(true)})}.cachedCount(3)// 预加载3个缓存项八、总结
ArkTS 的布局系统以声明式语法为核心,通过 Column/Row、Flex、Stack、Grid 等丰富的容器组件,覆盖了从简单线性排列到复杂二维网格的全场景需求。理解各容器的设计哲学与能力边界,是写出高效、优雅、可维护 UI 代码的前提。
在实际开发中,建议遵循以下原则:
- 骨架层用 Column/Row:页面整体结构采用线性布局搭建,保证性能与可读性
- 动态区用 Flex:标签流、按钮组等动态内容区域使用 Flex 的换行与弹性能力
- 叠加区用 Stack:弹窗、遮罩、水印等层叠场景使用 Stack 实现
- 矩阵区用 Grid:卡片矩阵、相册、仪表盘等二维排列使用 Grid 实现
- 跨端用 GridContainer:响应式场景下结合断点与栅格系统实现多端自适应
掌握这套布局体系,你就掌握了 ArkTS 声明式 UI 的骨架艺术,为构建高性能、高颜值的 HarmonyOS 应用打下坚实基础。
转载自:https://blog.csdn.net/u014727709/article/details/163198448
欢迎 👍点赞✍评论⭐收藏,欢迎指正