注:适用版本(HarmonyOS NEXT/5.0/API12+)
背景与痛点分析
多设备生态的挑战:手机、平板、车机、智能穿戴等不同屏幕尺寸和交互方式。
传统开发的局限性:重复适配、代码冗余、维护成本高。
HarmonyOS的解决方案:"一次开发,多端部署"(一多开发)的核心优势。
自适应布局的核心概念
原子化布局:基于组件化思想,拆解布局为可复用的最小单元。
响应式设计:通过断点、栅格系统、比例缩放适配不同屏幕。
多态控件:同一控件在不同设备上呈现不同交互形态(如手机上的列表 vs 手表上的卡片)。
资源动态加载:根据设备类型加载不同的布局文件或样式。
实现自适应布局的关键步骤
步骤1:明确设计原则
以内容为中心,优先保证核心功能一致性。
使用相对单位(vp/fp)而非固定像素,确保布局弹性。
遵循“最小差异”原则,减少多端适配的代码修改量。
实现自适应布局的关键步骤
步骤1:明确设计原则
以内容为中心,优先保证核心功能一致性。
使用相对单位(vp/fp)而非固定像素,确保布局弹性。
遵循“最小差异”原则,减少多端适配的代码修改量。
步骤2:利用ArkUI布局能力
弹性布局(Flex):通过Flex
容器实现元素的自适应排列。
网格布局(Grid):使用GridRow/GridCol
构建响应式栅格系统。
媒体查询(MediaQuery):监听屏幕属性(方向、分辨率)动态调整UI。
自适应布局的能力有 7 种,主要解决的是:窗口尺寸在【一定范围内】变化时,页面能够正常显示
自适应布局能力 |
使用场景 |
实现方式 |
拉伸能力 |
容器组件尺寸发生变化时,增加或减小的空间全部分配给容器组件内指定区域。 |
Flex布局 的flexGrow和flexShrink属性 |
均分能力 |
容器组件尺寸发生变化时,增加或减小的空间均匀分配给容器组件内所有空白区域。 |
Row组件 、Column组件 或Flex组件 的justifyContent属性设置为FlexAlign.SpaceEvenly |
占比能力 |
子组件的宽或高按照预设的比例,随容器组件发生变化。 |
基于通用属性的两种实现方式: |
缩放能力 |
子组件的宽高按照预设的比例,随容器组件发生变化,且变化过程中子组件的宽高比不变。 |
布局约束 的aspectRatio属性 |
延伸能力 |
容器组件内的子组件,按照其在列表中的先后顺序,随容器组件尺寸变化显示或隐藏。 |
基于容器组件的两种实现方式: 实现 配合Row组件 或Column组件 实现 |
隐藏能力 |
容器组件内的子组件,按照其预设的显示优先级,随容器组件尺寸变化显示或隐藏。相同显示优先级的子组件同时显示或隐藏。 |
布局约束 的displayPriority属性 |
折行能力 |
容器组件尺寸发生变化时,如果布局方向尺寸不足以显示完整内容,自动换行。 |
Flex组件 的wrap属性设置为FlexWrap.Wrap |
拉伸能力指的是容器尺寸发生变化时:将变化的空间,分配给容器内的【指定区域】。利用的是 2 个属性:
测试代码
@Entry
@Component
struct Demo01 {
// 绑定的宽度-默认 600
@State containerWidth: number = 600
// 底部滑块,可以通过拖拽滑块改变容器尺寸。
@Builder
sliderBuilder() {
Slider({
value: this.containerWidth, // 绑定的值
min: 400, // 最小值
max: 1000, // 最大值
style: SliderStyle.OutSet // 滑块在滑轨上
})
.blockColor(Color.White)
.width('60%')
.position({ x: '20%', y: '80%' })
.onChange((value)=>{
this.containerWidth = value
})
}
build() {
Stack({ alignContent: Alignment.TopStart }) {
// 标记现在的宽度
Text('宽度:' + this.containerWidth)
.zIndex(2)
.translate({ x: 20, y: 20 })
.fontColor(Color.Orange)
// 核心区域
Column() {
Column() {
Row() {
// 左
Row() {
Text('左')
.fontSize(20)
.fontColor(Color.White)
}
.justifyContent(FlexAlign.Center)
.width(150)
.height(290)
.backgroundColor('#c2baa6')
.flexShrink(1)
// 中
Row() {
Text('中')
.fontSize(30)
.fontColor(Color.White)
}
.width(300)
.height(290)
.backgroundColor('#68a67d')
.justifyContent(FlexAlign.Center)
.flexGrow(1)
// 右
Row() {
Text('右')
.fontSize(20)
.fontColor(Color.White)
}
.justifyContent(FlexAlign.Center)
.width(150)
.height(290)
.backgroundColor('#c2baa6')
.flexShrink(1)
}
.width(this.containerWidth)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.border({ width: 2, color: Color.Orange })
.backgroundColor(Color.Black)
}
// 底部滑块
this.sliderBuilder()
}
.width('100%')
.height('100%')
.backgroundColor(Color.Pink)
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
}
}
}
按照这个模板我们可以按照图标进行其他的能力测试
总结:
拉伸能力:flexGrow和flexShrink属性
均分能力:FLexALign.SpaceEvenly属性
占比能力:子组件宽高占比、layoutWeight
缩放能力:aspectRatio属性
延伸能力:List组件、Scroll组件
隐藏能力:displayPriority属性
折行能力:FLex组件,wrap属性、FLexWrap.Wrap