Harmony Os一多能力开发简要
1. 布局能力
1.1 自适应布局
元素可以根据相对关系自动变化以适应外部容器变化的布局能力。大致有七种自适应布局能力,这些布局可以独立使用,也可多种布局叠加使用。
- 拉伸能力:指容器组件尺寸发生变化时,增加或减小的空间全部分配给容器组件内指定区域。
//通过flexGrow和flexShrink属性,
//将多余的空间全部分配给图片,将不足的控件全部分配给两侧空白区域。
Row(){
Row().width(150)
.flexGrow(0).flexShrink(1)
Image($r("app.media.illustrator")).width(400)
.flexGrow(1).flexShrink(0)
Row().width(150)
.flexGrow(0).flexShrink(0)
}
- 均分能力:指容器组件爱你尺寸变化时,增加或减少的空间均匀分配给容器组件内所有空白区域。
实现:Row组件、Column组件或Flex组件的justifyContent属性设置为FlexAlign.SpaceEvenly
Column(){
Row(){
ForEach(this.list,(item:number) => {...})
}.width('100%')
//均匀分配父容器主轴方向的剩余空间
.justifyContent(FlexAlign.SpaceEvenly)
}
.width(this.rate * 100 + '%')
-
占比能力:子组件的宽或高按照预设的比例,随容器组件发生变化。
实现:基于通用属性的两种实现方式:- 将子组件的宽高设置为父组件宽高的百分比
- layoutWeight属性
Row(){
Column(){...}.layoutWeight(1)
Column(){...}.layoutWeight(1)
Column(){...}.layoutWeight(1) //设置子组件在父容器主轴方向的布局权重
}
.width(this.rate * 100 + '%')
4.缩放能力:
Column(){
Column(){
Image($r("app.media.illustrator"))
.width('100%').height('100%')
}
.aspectRatio(1) //固定宽高比
}
.height(this.sliderHeight)
.width(this.sliderWidth)
-
延伸能力:容器组件内的子组件,按照其在列表中的先后顺序,随容器组件尺寸变化显示或隐藏。
基本通过有滚轮容器就可以
Row({space : 10}){
//通过List组件实现隐藏能力
List({space: 10}){...}
.listDirection(Axis.Horzontal)
.width('100%')
}
.width(this.rate * 100 + '%')
-
隐藏能力:容器组件内的子组件,按照其预设的显示优先级,随容器组件尺寸变化显示或隐藏。相同显示优先级的子组件同时显示或隐藏。
实现:布局约束的displayPriority属性
Row(){ Image($r("app.media.favorite1")) .displayPriority(1) //设置布局优先级为1,数字越大优先级越大 Image($r("app.media.favorite2")) .displayPriority(2) Image($r("app.media.favorite3")) .displayPriority(3) Image($r("app.media.favorite4")) .displayPriority(2) Image($r("app.media.favorite5")) .displayPriority(1) } .width(this.rate * 100 + '%')
-
折行能力:容器组件尺寸发生变化时,如果布局方向尺寸不足以显示完整内容,自动换行。
Column(){ //通过Flex组件warp参数实现自适应折行 Flex({wrap:FlexWrap.Wrap, direction: FlexDirection.Row}){ ForEach(this.imageList,(item: Resource) => { Image(item).width(183).height(138) }) } .width(this.rate * 100 + '%') }
1.2 响应式布局
元素可以根据特定的特征(如窗口宽度,屏幕方向等)触发变化以适应外部容器变化的布局能力。响应式布局基于——断点,媒体查询,栅格等能力实现。
响应式布局能力 | 简介 |
---|---|
断点 | 将窗口宽度划分为不同的范围(即断点),监听窗口尺寸变化,当断点改变时同步调整页面布局。 |
媒体查询 | 媒体查询支持监听窗口宽度、横竖屏、深浅色、设备类型等多种媒体特征,当媒体特征发生改变时同步调整页面布局。 |
栅格布局 | 栅格组件将其所在的区域划分为有规律的多列,通过调整不同断点下的栅格组件的参数以及其子组件占据的列数等,实现不同的布局效果。 |
2.功能级一对多
应用开发至少包含两部分工作: UI页面开发和底层功能开发(部分需要联网的应用还会涉及服务端开发)。前面章节介绍了如何解决页面适配的问题,本章节主要介绍应用如何解决设备系统能力差异的兼容问题。
系统能力
系统能力(即SystemCapability,缩写为SysCap)指操作系统中每一个相对独立的特性,如蓝牙,WIFI,NFC,摄像头等,都是系统能力之一。每个系统能力对应多个API,随着目标设备是否支持该系统能力共同存在或消失。
与系统能力相关的,有支持能力集、联想能力集和要求能力集三个核心概念。
- 支持能力集:设备具备的系统能力集合,在设备配置文件中配置。
- 要求能力集:应用需要的系统能力集合,在应用配置文件中配置。
- 联想能力集:开发应用时IDE可联想的API所在的系统能力集合,在应用配置文件中配置。
说明
- 只有当应用要求能力集是设备支持能力集的子集的时候,应用才可以在该设备上分发、安装和运行。
- 可以访问系统能力列表了解全量的系统能力。
动态逻辑判断
如果某个系统能力没有写入应用的要求能力集中,那么在使用前需要判断设备是否支持该系统能力。
- 方法1:HarmonyOS定义了API canIUse帮助开发者来判断该设备是否支持某个特定的syscap。
if (canIUse("SystemCapability.Communication.NFC.Core")) { console.log("该设备支持SystemCapability.Communication.NFC.Core");} else { console.log("该设备不支持SystemCapability.Communication.NFC.Core");}
- 方法2:开发者可通过import的方式将模块导入,若当前设备不支持该模块,import的结果为undefined,开发者在使用其API时,需要判断其是否存在。
import controller from '@kit.ConnectivityKit'; try { controller.enableNfc(); console.log("controller enableNfc success");} catch (busiError) { console.log("controller enableNfc busiError: " + busiError);}
说明
- 如果某系统能力是应用运行必须的,则要将其写入到应用的要求能力集中,以确保应用不会分发和安装到不符合要求的设备上。
- 如果某系统能力不是应用运行必须的,则可以在运行时做动态判断,这样可以最大程度扩大应用的适用范围。
配置联想能力集和要求能力集
- IDE会根据创建的工程所支持的设备自动配置联想能力集和要求能力集,同时也支持开发者修改。
// syscap.json
{
"devices": {
"general": [ // 每一个典型设备对应一个syscap支持能力集,可配置多个典型设备
"default",
"tablet"
],
"custom": [ // 厂家自定义设备
{
"某自定义设备": [
"SystemCapability.Communication.SoftBus.Core"
]
}
]
},
"development": { // addedSysCaps内的sycap集合与devices中配置的各设备支持的syscap集合的并集共同构成联想能力集
"addedSysCaps": [
"SystemCapability.Communication.NFC.Core"
]
},
"production": { // 用于生成rpcid,慎重添加,可能导致应用无法分发到目标设备上
"addedSysCaps": [], // devices中配置的各设备支持的syscap集合的交集,添加addedSysCaps集合再除去removedSysCaps集合,共同构成要求能力集
"removedSysCaps": [] // 当该要求能力集为某设备的子集时,应用才可被分发到该设备上
}
}
说明
- 对于要求能力集,开发者修改时要十分慎重,修改不当会导致应用无法分发和安装到目标设备上。
- 对于联想能力集,通过增加系统能力可以扩大IDE可联想的API范围。但要注意这些API可能在某些设备上不支持,使用前需要判断。
3.工程级一对多
工程级一多需要考虑如何实现一套代码同时能部署到多种不同设备上,代码工程如何组织。
应用程序包结构
在进行应用开发时,一个应用通常包含一个或多个Module。Module是HarmonyOS应用/服务的基本功能单元,包含了源代码、资源文件、第三方库及应用/服务配置文件,每一个Module都可以独立进行编译和运行。
Module分为“Ability”和“Library”两种类型:
- “Ability”类型的Module编译后生成HAP包。
- “Library”类型的Module编译后生成HAR包。
HarmonyOS的应用以APP Pack形式发布,其包含一个或多个HAP包。HAP是HarmonyOS应用安装的基本单位,HAP可以分为Entry和Feature两种类型:
- Entry类型的HAP:应用的主模块。在同一个应用中,同一设备类型只支持一个Entry类型的HAP,通常用于实现应用的入口界面、入口图标、主特性功能等。
- Feature类型的HAP:应用的动态特性模块。Feature类型的HAP通常用于实现应用的特性功能,一个应用程序包可以包含一个或多个Feature类型的HAP,也可以不包含。
部署模型
“一多”有两种部署模型:
- 部署模型A:不同类型的设备上按照一定的工程结构组织方式,通过一次编译生成相同的HAP(或HAP组合)。
- 部署模型B:不同类型的设备上按照一定的工程结构组织方式,通过一次编译生成不同的HAP(或HAP组合)。
开发者可以从应用UX设计及应用功能两个维度,结合具体的业务场景,考虑选择哪种部署模型。当然,也可以借助设备类型分类,快速做出判断。
从屏幕尺寸、输入方式及交互距离三个维度考虑,可以将常用类型的设备分为不同泛类:
- 默认设备、平板
- 车机、智慧屏
- 智能穿戴
- ……
对于相同泛类的设备,优先选择部署模型A,对于不同泛类设备,优先选择部署模型B。
说明
- 应用在不同泛类设备上的UX设计或功能相似时,可以使用部署模型A。
- 应用在同一泛类不同类型设备上UX设计或功能差异非常大时,可以使用部署模型B,但同时也应审视应用的UX设计及功能规划是否合理。
- 本小节引入部署模型A和部署模型B的概念是为了方便开发者理解。实际上在开发多设备应用时,如果目标设备类型较多,往往是部署模型A和部署模型B混合使用。
- 不管采用哪种部署模型,都应该采用一次编译。
工程结构
“一多”推荐在应用开发过程中使用如下的“三层工程结构”。
-
common(公共能力层):用于存放公共基础能力集合(如工具库、公共配置等)。
common层不可分割,需编译成一个HAR包,其只可以被products和features依赖,不可以反向依赖。
-
features(基础特性层):用于存放基础特性集合(如应用中相对独立的各个功能的UI及业务逻辑实现等)。
各个feature高内聚、低耦合、可定制,供产品灵活部署。不需要单独部署的feature通常编译为HAR包,供products或其它feature使用。需要单独部署的feature通常编译为Feature类型的HAP包,和products下Entry类型的HAP包进行组合部署。features层可以横向调用及依赖common层,同时可以被products层不同设备形态的HAP所依赖,但是不能反向依赖products层。
-
products(产品定制层):用于针对不同设备形态进行功能和特性集成。
products层各个子目录各自编译为一个Entry类型的HAP包,作为应用主入口。products层不可以横向调用。
代码工程结构抽象后一般如下所示:
/application├── common # 可选。公共能力层, 编译为HAR包或HSP包├── features # 可选。基础特性层│ ├── feature1 # 子功能1, 编译为HAR包或HSP包或Feature类型的HAP包│ ├── feature2 # 子功能2, 编译为HAR包或HSP包或Feature类型的HAP包│ └── ...└── products # 必选。产品定制层 ├── wearable # 智能穿戴泛类目录, 编译为Entry类型的HAP包 ├── default # 默认设备泛类目录, 编译为Entry类型的HAP包 └── ...
说明
- 部署模型不同,相应的代码工程结构也有差异。部署模型A和部署模型B的主要差异点集中在products层:部署模型A在products目录下同一子目录中做功能和特性集成;部署模型B在products目录下不同子目录中对不同的产品做差异化的功能和特性集成。
- 开发阶段应考虑不同类型设备间最大程度的复用代码,以减少开发及后续维护的工作量。
# 智能穿戴泛类目录, 编译为Entry类型的HAP包 ├── default # 默认设备泛类目录, 编译为Entry类型的HAP包 └── …
说明
- 部署模型不同,相应的代码工程结构也有差异。部署模型A和部署模型B的主要差异点集中在products层:部署模型A在products目录下同一子目录中做功能和特性集成;部署模型B在products目录下不同子目录中对不同的产品做差异化的功能和特性集成。
- 开发阶段应考虑不同类型设备间最大程度的复用代码,以减少开发及后续维护的工作量。
- 整个代码工程最终构建出一个APP包,应用以APP包的形式发布到应用市场中。