一、一多开发核心概念(1+8+N模式)
目标:一次开发多端部署 解决的问题:
1、界面级一多:适配不同屏幕尺寸
2、功能级一多:设备功能兼容性处理(CanIUser)
3、工程级一多:项目架构管理(三成架构HAP、HAR、HSP)
二、界面级一多解决方法
1、自适应布局
能力 | 核心属性/组件 | 代码示例 |
拉伸 | flexGrow/flexShrink | .flexGrow(1).flexShrink(1) |
均分 | justifyContent: SpaceEvenly | Row().justifyContent(FlexAlign.SpaceEvenly) |
占比 | layoutWeight 或百分比宽高 | .width('50%').layoutWeight(1) |
缩放 | aspectRatio | .aspectRatio(1.5) |
延伸 | List/Scroll + Row | List().listDirection(Axis.Horizontal) |
隐藏 | displayPriority | .displayPriority(2) |
折行 | FlexWrap.Wrap | Flex({ wrap: FlexWrap.Wrap }) |
2、响应式布局
2-1、断点系统
断点 | 范围(vp) | 典型设备 |
xs | [0, 320) | 智能手表 |
sm | [320, 600) | 手机竖屏 |
md | [600, 840) | 折叠屏/横屏 |
lg | [840, +∞) | 平板/PC |
// 在Ability中监听窗口变化
windowObj.on('windowSizeChange', (size) => {
const widthVp = size.width / density;
AppStorage.set('currentBreakpoint', calculateBreakpoint(widthVp));
});
2-2、媒体查询
// 创建监听器
const listener = mediaquery.matchMediaSync('(320vp<=width<600vp)');
// 注册回调
listener.on('change', (res) => {
if (res.matches) AppStorage.set('breakpoint', 'sm');
});
// 移除监听
listener.off('change');
2-3栅格布局
GridRow({
columns: { sm: 4, md: 8, lg: 12 },
gutter: 10
})
/*--------------------------------------------*/
//GridRow:定义行布局规则
GridRow({
columns: { sm: 4, md: 8, lg: 12 },
gutter: 10
})
/*--------------------------------------------*/
//GridCol:定义列占比与偏移
GridCol({
span: { sm: 2, md: 4 },
offset: { md: 1 }
})
场景 | 推荐方案 | 优势 |
微调元素尺寸 | 自适应布局(占比/拉伸) | 简单高效,代码侵入性低 |
多设备显隐逻辑 | 响应式布局(媒体查询) | 精确控制不同断点下的UI表现 |
复杂多列布局 | 栅格系统 | 内置响应规则,维护性强 |
全局断点状态管理 | BreakpointSystem工具 | 统一管理断点,避免重复监听 |
3、界面级一多断点
import window from '@ohos.window'
import display from '@ohos.display'
import UIAbility from '@ohos.app.ability.UIAbility'
export default class EntryAbility extends UIAbility {
private windowObj?: window.Window
private curBp: string = ''
//...
// 根据当前窗口尺寸更新断点
private updateBreakpoint(windowWidth: number) :void{
// 将长度的单位由px换算为vp
let windowWidthVp = windowWidth / display.getDefaultDisplaySync().densityPixels
let newBp: string = ''
if (windowWidthVp < 320) {
newBp = 'xs' // 超小屏
} else if (windowWidthVp < 600) {
newBp = 'sm' // 小屏
} else if (windowWidthVp < 840) {
newBp = 'md' // 中屏
} else {
newBp = 'lg' // 大屏
}
if (this.curBp !== newBp) {
this.curBp = newBp
// 使用状态变量记录当前断点值
AppStorage.setOrCreate('currentBreakpoint', this.curBp)
}
}
onWindowStageCreate(windowStage: window.WindowStage) :void{
windowStage.getMainWindow().then((windowObj) => {
this.windowObj = windowObj
// 获取应用启动时的窗口尺寸
this.updateBreakpoint(windowObj.getWindowProperties().windowRect.width)
// 注册回调函数,监听窗口尺寸变化
windowObj.on('windowSizeChange', (windowSize)=>{
this.updateBreakpoint(windowSize.width)
})
});
// ...
}
//...
}
- 技术栈:
- 鸿蒙特定 API:基于鸿蒙系统的
@ohos.window
、@ohos.display
和@ohos.app.ability.UIAbility
模块进行开发,充分利用鸿蒙系统提供的窗口管理、显示信息获取以及应用能力相关的原生 API。- 核心点:
- 窗口尺寸监听:在
onWindowStageCreate
方法中,通过windowStage.getMainWindow().then
获取主窗口对象,随后利用windowObj.on('windowSizeChange', ...)
注册回调函数,实时监听窗口尺寸变化,这是实现屏幕适配的关键起始步骤。- 断点计算与更新:
updateBreakpoint
方法将获取到的窗口宽度从像素(px
)换算为虚拟像素(vp
),根据不同的vp
范围确定对应的断点值(xs
、sm
、md
、lg
)。当计算出的新断点与当前断点不同时,更新当前断点并通过AppStorage.setOrCreate
方法记录在状态变量中,以便应用其他部分根据断点值进行不同的布局或功能调整。
三、总结
本文围绕 “一多开发” 这一核心概念展开,着重探讨了其在界面级的实现方式。“一多开发” 旨在达成一次开发多端部署,解决界面、功能及工程等层面的适配与管理问题。
在界面级,通过自适应布局、响应式布局两种主要方式实现对不同屏幕尺寸的适配。自适应布局借助如flexGrow
、justifyContent
等多种属性和组件,能简单高效地微调元素尺寸;响应式布局则通过断点系统、媒体查询和栅格布局,可更精准地控制不同设备下的 UI 表现,满足多设备显隐逻辑和复杂多列布局等场景需求。
结合提供的鸿蒙开发代码示例,其基于鸿蒙特定 API 实现了窗口尺寸监听与断点计算更新,这是界面适配的关键技术点。通过监听窗口变化获取尺寸信息,换算为vp
后确定断点值并记录,为应用根据不同屏幕尺寸调整布局和功能提供依据。