【HarmonyOS】ArKUI框架

目录

概述

声明式开发范式

基于ArKUI的项目

[• 1.创建资源文件](#• 1.创建资源文件)

[• 2.引用资源](#• 2.引用资源)

[• 3.引用系统资源:](#• 3.引用系统资源:)

[• 系统资源有哪些](#• 系统资源有哪些)

[• 4. 在配置和资源中引用资源](#• 4. 在配置和资源中引用资源)

声明式语法

UI描述规范

UI组件概述

组件化

组件渲染控制语法

修改应用名称和图标


概述

• 在HarmonyOS应用开发中,前期官方推出了 两种UI开发框架
• 一个是基于Java的UI开发框架- 已经废弃
• 一个是基于 ArkTS 的UI开发框架
• 在 基于ArkTS的UI开发框架 中,应用包括 组件 和 页面 ,组件是界面搭建与显示的最小单位,通过组件的组合可以构建出内容丰富的界面,页面(Page)是框架最小的调度分割单位,应用可以有
多个功能页面,每个页面进行单独的文件管理,并通过路由API实现页面跳转和调度管理
• 基于 ArkTS的声明式开发范式 采用 TS 语言,并对其进行了声明式UI语法扩展,从 组件 、 动效 和 状态管理 三个维度提供了UI绘制能力
• UI后端引擎实现了方舟开发框架的6种基本能力,包括UI组件、布局、动画、绘制、交互事件和平台API通道
• 采用 声明式开发范式 来搭建应用界面

声明式开发范式

• 基于ArkTS声明式开发范式具有以下 主要特点 :
• 1) 开箱即用的组件 :框架提供丰富的系统预置组件,可以通过链式调用的方式设置系统组件的渲染效果。开发者可以组合系统组件为自定义组件,通过这种方式将页面组件化为一个个独立的UI单元,实现页面不同单元的独立创建、开发和复用,使页面具有更强的工程性。
• 2) 丰富的动效接口 :提供s vg标准的绘制图形能力,同时开放了丰富的动效接口,开发者可以通过封装的物理模型或者调用动画能力接口来实现自定义动画轨迹。
• 3) 状态与数据管理 :状态数据管理作为基于A rkTS的声明式开发范式的特色,通过功能不同的装饰器给开发者提供了清晰的页面更新渲染流程和管道。状态管理包括UI组件状态和应用程序状态,两者协作可以使开发者完整地构建整个应用的数据更新和UI渲染。
• 4) 系统能力接口 :使用基于A rkTS的声明式开发范式的方舟开发框架,还封装了丰富的系统能力接口,开发者可以通过简单的接口调用,实现从UI设计到系统能力调用的极简开发。
• 基于ArkTS的声明式开发范式 整体架构 ,最上层是应用,然后是声明式UI前端,包括范式语法基础前端、UI/布局/动画组件、状态管理,再往下是语言运行时和声明式UI后端引擎,渲染引擎,
平台适配层等。

• 声明式UI前端提供了 UI开发范式的基础语言规范 ,并提供内置的UI组件、布局和动画,提供了多种状态管理机制,为应用开发者提供一系列接口支持。
• 语言运行时选用 方舟语言运行时 ,提供了针对UI范式语法的解析能力、跨语言调用支持的能力和TS语言高性能运行环境。
• 声明式UI后端引擎 提供了兼容不同开发范式的UI渲染管线,提供多种基础组件、布局计算、动效、交互事件,提供了状态管理和绘制能力。
• 渲染引擎 提供了高效的绘制能力,将渲染管线收集的渲染指令,绘制到屏幕能力。
• 平台适配层 提供了对系统平台的抽象接口,具备接入不同系统的能力,如系统渲染管线、生命周期调度等。

基于ArKUI的项目


• 文件结构
• 应用的主要文件放置在src/main目录下
• ets目录:Ability和 页面文件
• 一般一个 Ability 放到一个子目录中
• Pages目录下存放所有 页面文件 :用
于描述页面UI布局、样式、事件交互
和页面逻辑等
• resources目录:资源文件
• 模块配置文件:module.json5
• 资源目录 resou rces 文件夹位于s rc/main下,应用的资源文件(字符串、图片、音频等)统一存放于resou rces目录下,便于开发者使用和维护。resou rces目录包括三大类目录,一类为base目录,一类为限定词目录,另一类为raw file目录。

|----------|-----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|--------------------------------------------------------------------------|
| 分类 | base目录 | 限定词目录 | rawfile目录 |
| 组织形式 | 资源默认存在的目录 ,当应用的resources目录中没有与设备状态匹配的限定词目录时,会自动引用该目录中的资源文件。base目录下可以有资源组目录,用于存放字符串、颜色、布尔值、媒体、动画、布局等资源文件 | 需要开发者自行创建。目录名称由一个或多个表征应用场景或设备特征的限定词组合而成。其二级子目录为资源组目录,用于存放字符串、颜色、布尔值、媒体、动画、布局等资源文件 | 原始文件目录,其中的文件不会根据设备状态而匹配不同的资源。支持创建多层子目录,目录名称可以自定义,文件内可以自由放置各类资源文件 |
| 编译方式 | 目录中的资源文件会被编译成二进制文件,并赋予资源ID | 目录中的资源文件会被编译成二进制文件,并赋予资源文件ID | 目录中的资源文件会被直接打包进应用,不编译,也不会被赋予资源文件ID |
| 引用方式 | 通过指定资源类型(type)和资源名称(name)来引用 | 通过指定资源类型(type)和资源名称(name)来引用 | 通过指定文件路径和文件名来引用 |

• 资源组目录是 base 目录与限定词目录下面可以创建的目录(包括 elemen t 、 media 和 p ro file ),资源组目录用于存放特定类型的资源文件

|-----------|---------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| 资源组目录 | 目录说明 | 资源文件 |
| element | 元素资源,每一类数据都采用相应的JSON文件进行表示,元素主要包 括以下类型资源:布尔型、颜色、浮点型、整型数组、整型、样式、复数形式、字符串数组、字符串 | 每个文件中只能包含一类数据资 源,文件名称建议与资源类型保持一致。如:boolean.json、 color.json、float.json、 intarray.json、integer.json、 pattern.json、plural.json、 strarray.json、string.json |
| media | 表示媒体资源,包括图片、音频、 视频等非文本格式的文件。图片格 式支持JPEG、PNG、GIF、SVG、WEBP 、BMP。音视频格式支持H.263、 H.264 AVC、BP、MPEG-4 SP、VP8。 | 文件名可自定义,一般扩展名对 应相应的格式,例如:icon.png 、pic.jpg、song.3gp、 movie.mp4等 |
| profile | 表示其它类型文件,以原始文件形 式保存。 | 文件名可自定义。 |

• 1.创建资源文件

• 在resou rces目录下,可按照限定词目录和资源组目录的说明创建子目录和目录内的文件。对应文本资源文件可以直接进行编辑,图片、音视频资源放置到相应的目录下即可。
• 可以通过提供的可视化的向导创建资源,在项目的resou rces目录上,点击右键菜单选择" New→Resource File "
• 以JSON格式保存的资源文件内部是一个 JSON对象 ,例如资源文件s t ring.josn的
内容如下:

复制代码
{
"string": [
{
"name": "entrydesc",
"value": "description"
},
{
"name": "MainAbilitydesc",
"value": "description"
},
{
"name": "MainAbilitylabel",
"value": "label"
}
]
}

• 2.引用资源

• 基本格式
$r('app.type.name')
• app 代表的是应用内resou rces目录中定义的资源,是固定的;
• type 代表资源类型或资源的存放位置,type可以是colo r、float、st ring、 plural、media等具体的资源类型
• name 代表资源名,它由开发者定义。

复制代码
$r('app.string.entrydesc')
$r("app.string.entrydesc") // 单双引号相同
$r('app.string.message', "100M") //替代参数%s

{
"string":[
{
"name":"message",
"value":"The length is %s."
}
]
}

• 引用 raw file 目录下资源的一般形式为:

$r('filename')
• 假设,raw file目录下有一个images目录,在images目录中有个 logo.jpg 图片,则在代码中引用该资源图片的代码如下:

复制代码
$rawfile('images/logo.jpg')

• 3.引用系统资源:

$r('sys.type.resource_id')
• sys 代表是系统资源;type代表资源类型, type 可以取color、float、string、media等; resou rce_id 代表资源id,系统预定义了一些资源id可
下面是引用系统资源一些例子:

复制代码
Text('您好')
.fontColor($r('sys.color.id_color_emphasize'))
.fontSize($r('sys.float.id_text_size_headline1'))
.fontFamily($r('sys.string.id_text_font_family_medium'))
.backgroundColor($r('sys.color.id_color_palette_aux1'))
Image($r('sys.media.ic_app'))
.border({color: $r('sys.color.id_color_palette_aux1'),
radius: $r('sys.float.id_corner_radius_button'),
width: 2})
.height(60)
.width(80)

• 系统资源有哪些

|--------|-------------------------------|----------------------------------------------|
| 分类 | ID值 | 说明 |
| 颜色 | id_color_foreground | 前景色,浅色模式对应值为#000000,即黑色,深色模式对应值为#FFFFFF,即白色 |
| 颜色 | id_color_background | 背景色,和前景色恰好相反 |
| 颜色 | id_color_emphasize | 高亮色,浅色模式对应值为#0A59F7,蓝色,深色模式下对应的浅蓝色,值为#317AF7 |
| 颜色 | id_color_warning | 告警色,浅色模式对应值为#E84026,一种红色,深色模式下,对应的是值为#D94838 |
| 颜色 | ... | 其它还有很多,这里省略了 |
| 透明度 | id_alpha_content_primary | 不透明度,对应的alpha值为在浅色模式下是0.9,深色模式下是0.86 |
| 透明度 | id_alpha_content_secondary | 二级不透明度,对应的alpha值为0.6 |
| 透明度 | id_alpha_separator_line | 分割线不透明,在浅色模式下对应的alpha值为0 |
| 透明度 | ... | 其它还有很多,这里省略了 |
| 圆角大小 | id_corner_radius_tips_toast | toast圆角,对应值为18vp |
| 圆角大小 | id_corner_radius_button | 大按钮圆角,对应值为20vp |
| 圆角大小 | id_corner_radius_small_button | 小按钮圆角,对应值为14vp |
| 圆角大小 | ... | 其它还有很多,这里省略了 |
| 文本大小 | id_text_size_headline1 | 标题1字体,对应大小为96vp,常用于锁屏时钟或天气信息显示字体 |
| 文本大小 | id_text_size_body1 | 正文1字体,对应大小为16fp,一般用于段落正文 |
| 文本大小 | id_text_size_caption | 说明文本大小,对应大小为10vp |
| 文本大小 | ... | 其它还有很多,这里省略了 |
| 边距大小 | id_default_padding_start | 默认的起始位置内边距,对应的值为12vp,常用于左侧边缘 |
| 边距大小 | id_default_padding_top | 上侧边距,对应值为24vp |
| 边距大小 | id_text_margin_vertical | 文本上下间隔边距,对应值为2vp |
| 边距大小 | .. | 其它还有很多,这里省略了 |

• 4. 在配置和资源中引用资源

• 资源除了可以在源代码中引用外,还可以在配置文件引用。在配置文件中引用资源的格式为:" 资源名 ",例如配置description和icon值时引用资源的代码如下: **"description": "string:EntryAbility_desc"**
"icon": "$media:icon"
• 资源在资源文件之间也可以相互引用,引用方式和在配置文件中 引用资源相同 。在配置文件或资源文件中引用资源时要注意资源类型的一致性。

声明式语法

UI描述规范

• Stage模型

UI组件概述

• 一个页面(Page)对应一个ets文件,一个页面内可以有若干个组件,
基于ArkTS语言定义组件采用struct关键字,并通过生成器函数
(build ())构建组件内的内容,组件内可以包含其它组件,其它组件可以系统的内置组件,也可以是自定义的组件。
• 一个页面必须有且只有一个 入口组件 ,入口组件有 @Entr y装饰器修饰 。

复制代码
@Entry //入口装饰器
@Component //组件装饰器
struct MyIndexComponent {
@State mydata: string = '' //状态数据
build() { //生成器函数
//省略了构造内部组件
}
}
@Component
struct OtherComponent {
@State msg: string = ''
build() {
//构造内部组件
}
}

• 在基于ArkTS的HarmonyOS应用的UI开发规范中, 定义了很多装饰器 , 如@Entr y、@Component、@State等,这些装饰器用于装饰类、结构、方法和变量等。

|---------------|-------------------|-------------------------------------------------------|
| 装饰器 | 可以装饰内容 | 说明 |
| @Component | struct | 结构体(struct)在被装饰后具有基于组件的能力,需要实现build方法来更新UI |
| @Entry | struct | 组件在被装饰后会作为页面的入口组件,页面加载时将被渲染显示 |
| @Preview | struct | 自定义的组件被@Preview装饰,则可以在DevEco Studio的预览器中进行预览 |
| @CustomDialog | struct | 用于装饰自定义弹窗 |
| @Observed | class | 类被装饰后,则该类中的数据变更被UI页面管理 |
| @ObjectLink | 已被@Observed装饰类的对象 | 被装饰的状态数据被修改时,则在父组件或者其它兄弟组件内与它关联的状态数据所在的组件都会更新UI |
| @Builder | 方法 | 被装饰的方法可以在一个自定义组件内快速生成多个布局内容 |
| @Extend | 方法 | 装饰器将新的属性函数添加到内置组件上,通过@Extend装饰器可以快速定义并复用组件的自定义样式 |
| @Prop | 基本数据类型 | 装饰的状态数据用于在父组件和子组件之间建立单向数据依赖关系。修改父组件关联数据时,更新当前组件的UI |
| @State | 基本数据类型,类,数组 | 装饰的状态数据被修改时会触发组件的build方法进行UI界面更新 |
| @Link | 基本数据类型,类,数组 | 装饰的内容在父子组件之间的双向数据绑定,父组件的内部状态数据作为数据源,任何一方所做的修改都会反映给另一方 |
| @Provid | 基本数据类型,类,数组 | 装饰的数据作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染 |
| @Consume | 基本数据类型,类,数组 | 装饰的变量在感知到@Provide装饰的变量更新后,会触发当前自定义组件的重新渲染 |

• 在定义的组件的生成器方法(build ())内,可以 声明描述UI结构 ,可以在其中创建内置的布局组件和基本组件,如内置布局Row、Column,内置组件Text、Button等。

复制代码
@Entry //入口装饰器
@Component //组件装饰器
struct Index{
bt_text: string = '确定'
build() {
Row() { //创建行布局
Text( "您好" ) //创建文本组件
.fontSize(50)
Button(this.bt_text) //创建按钮组件
.fontSize(30)
.margin(10)
MyComponent () //创建自定义组件
}
}
}
// 自定义组件
@Component
struct MyComponent {
build() {
//构建布局和组件
}
}

• 在生成器方法(build ())内构建的界面组件组成是 一棵树型结构 ,组件包括 容器 和 普通 组件,容器可以认为是特殊的组件,其内部可以放置别的组件或容器,容器组件也称为布局,普通组件一般不能包含其它组件。

• 容器组件和普通组件都可以 通过调用其属性方法 进行各种属性配置,调用一般以" . "链式调用的方式,例如:

复制代码
Row() { //构造Row布局
Image('button.png') //构造Image
.alt('over.png') //调用alt方法
.width(100) //调用width
.height(50) //调用height
}.padding(16) //设置Row的内边距

• 组件还可以 设置事件方法 ,并可以在事件方法的回调中添加组件响应逻 辑代码,实现事件监听。如为Button组件添加onClick方法,在onClick方法的回调中添加点击响应逻辑等。

复制代码
Button('OK')
.onClick(()=>{
//点击处理代码
})
)

• 需要注意 ,生成器函数build( )是用来构造UI界面的,因此 不能 在其中直接定义变量或调用一般的函数,例如:

复制代码
@Entry //入口装饰器
@Component //组件装饰器
struct Index{
test(){
return "OK"
}
build() {
let n: number = 1 // 错误,不允许定义变量
test() // 错误,不能直接调用函数
Column() {
Text( this.test() ) // 这里可以调用test
}
}
}

组件化

• 由装饰器 @Component 装饰的struct结构体就具备了 组件化能力 ,是一个独立的组件,这种组件也称为 自定义组件 ,自定义组件在其生成器build方法里进行UI结构描述,使其具有丰富的界面展示。自定义组件具有以下特点:
• 1)可组合:自定义可以由其它组件组合而成,允许开发者在自定义组件内使用内置组件、其它组件、公共属性和方法等。
• 2)可重用:自定义组件可以被其它组件使用,作为别的组件的一部分,并且可以重用,可以作为不同的实例在不同的父组件或容器中使用。
• 3)数据驱动更新:自定义组件由状态变量的数据驱动,可以实现UI自动刷新。
• 4)生命周期:自定义组件具有生命周期,具有相应的回调方法,开发者可以重写回调方法以实现组件的自身的业务功能和逻辑。
• 5)生成器方法:自定义组件必须定义生成器build方法,该方法用于构建组件内容。
• 6)无构造函数:自定义组件不能定义构造函数,组件内容的初始化构造是通过build完成的。

复制代码
@Component // 组件装饰器
struct MyComponent { // 自定义组件
build() {
Column() { // 列容器组件
Text('Hello') // 文本组件,文字为Hello
.fontColor(Color.Red) // 字体红色
}.alignItems(HorizontalAlign.Center) // 内容居中
}
}
@Component
struct OtherComponent {
build() {
Column() {
MyComponent() //创建MyComponent 实例
Text('Hello').fontSize(20)//使用系统内置组件Text
MyComponent() //再次创建MyComponent 实例
}
}
}

• @Entr y 装饰的自定义组件是页面的默认 入口组件 ,一个ets源文件中,最多只能存在一个

复制代码
@Entry
@Component
struct Index{ //该组件会被渲染和显示
build() {
Column() { //Column是系统内置容器组件
Text('Hello')
.fontColor(Color.Red)
}
}
}
@Component
struct MyText { //该组件不会被渲染和显示,但可以被引用
build() {
Column() {
Text('Good')
.fontColor(Color.Blue)
}
}
}

• 由 @Builder 装饰的方法用于 定义组件 的声明式UI描述,可以在一个自定义组件内快速生成多个布局内容, @Builder 装饰方法的功能和语法规范与 build 函数相同,并可以在build内调用。

复制代码
@Entry
@Component
struct Index {
mySize : number = 10;
@Builder // Builder装饰器
SquareText(title: string) { // 该方法可以在build中被调用
Text(title)
.width( this.mySize )
.height( this.mySize )
}
build() {
Column() {
Row() {
this.SquareText("A") // 调用被Builder装饰的方法
this.SquareText("B") // 调用被Builder装饰的方法
}
}
}
}

• @Styles 装饰器可以将新的 属性函数 添加到基本组件上,如Text、Column、Button等
• @Styles 仅支持 通用属性 。通过@Styles装饰器可以快速定义并复用组件的自定义样式,当在组件外定义时需带上function关键字,组件内定义时不需要。

复制代码
@Styles //通过@Styles装饰
function yourBGStyle() { 
.backgroundColor(Color.Green)
}
@Entry
@Component
struct Test {
@Styles myBGStyle() { //省略了function关键字
.backgroundColor(Color.Blue)
}
build() {
Column({ space: 10 }) {
Text("您好")
.yourBGStyle()
Text("我的")
.myBGStyle()
}
}
}

• 通过 @Extend 装饰器可以 扩展内置组件 ,即可以将新的属性函数添加到内置组件上,如扩展Text、Column、Button等。通过@Extend装饰器可以快速定义并复用组件的自定义样式。

复制代码
@Extend(Text) //扩展Text
function myStyle(fontSize: number) {
.fontColor(Color.Red)
.fontSize(fontSize)
.fontStyle(FontStyle.Italic)
}
@Entry
@Component
struct Test {
build() {
Row( ) {
Text("您好")
.myStyle(16) // 调用扩展的功能
}
}
}

组件渲染控制语法

• 渲染控制分为: 条件渲染 和 循环渲染
• 1. 条件渲染 :在创建组件时,根据条件进行

复制代码
@Entry
@Component
struct Test {
count:number = 100
build() {
Column() { //容器组件
if (this.count < 0) {
Text('count为负数')
} else if (this.count == 0) {
Text('ccount为0')
} else { //内部嵌套if-else
if ( this.count % 2 == 0) {
Text('count是偶数').fontSize(26)
Divider().height(1)
} else {
Text('count是奇数').fontSize(26)
Divider().height(1)
}
}
}
if(this.count>100){ //错误,没有在组件容器内
Text('count超出了100')
}
}
}

• 2. 循环渲染
• 循环渲染可以批量处理组件,开发框架提供循环渲染可以迭代数组,并可以根据每个数组项创建相应的组件。
• 循环渲染可以使用 ForEach 函数

复制代码
@Entry
@Component
struct MyComponent {
@State arr: string[] = ['张三', '李四', '王五']
build() {
Column() {
ForEach(
this.arr, // 参数1:数组
(item: string, index: number) => { //参数2:迭代器函数
Row() {
Text(`下标: ${index}`)
Text(`姓名:${item}`)
},
(item: string, index: number) => { //参数3:迭代器函数
return index + item //为每个数组项生成唯一
} //且持久的键值,可不写
)
}
}
}

注意:
• 条件渲染语句 必须在容器组件内 使用,某些容器组件会限制子组件的类型或数量,在将if放置在这些组件内时,这些限制将应用于if和else语句内创建的组件。例如,Grid组件的子组件仅支持GridItem组件,在Grid组件内使用if时,则if条件语句内仅允许使用GridItem组件。另外,i f条件语句可以使用状态变量。
• 循环渲染也 必须在容器组件内 使用,生成的子组件允许在ForEach的父容器组件中,允许子组件生成器函数中包含if/else条件渲染,同时也允许ForEach包含在if/else条件渲染语句中。
• 循环渲染中 子项生成器函数的调用顺序 不一定 和 数组中的数据项相同 ,子项生成器和键值生成器函数的执行顺序也是不确定的。

修改应用名称和图标


  • 基于ArkTS的声明式UI开发框架ArkUI,含有ArkUI的HarmonyOS应用一般包含多个能力(Ability)。
  • PageAbility可以包含多个页面(Page),每个页面对应一个ets文件,每个页面内部可以包含多个组件,其中必须有且只有一个入口(Entr y)组件,组件可以嵌套,形成组件树,加以利用项目中的各种文本、图片、音视频等资源,进而构建丰富的界面。
  • 基于ArkTS语言的声明式语法提供了开发HarmonyOS应用的基本规范,规范中定义了大量的装饰器,为应用提供高效的开发基础,
  • UI界面构成采用的组件化方式,组件可以进行条件渲染和循环渲染等。
相关推荐
whysqwhw25 分钟前
鸿蒙AVSession Kit
harmonyos
whysqwhw2 小时前
鸿蒙各种生命周期
harmonyos
whysqwhw3 小时前
鸿蒙音频编码
harmonyos
whysqwhw3 小时前
鸿蒙音频解码
harmonyos
whysqwhw3 小时前
鸿蒙视频解码
harmonyos
whysqwhw3 小时前
鸿蒙视频编码
harmonyos
ajassi20004 小时前
开源 Arkts 鸿蒙应用 开发(十八)通讯--Ble低功耗蓝牙服务器
华为·开源·harmonyos
前端世界5 小时前
在鸿蒙应用中快速接入地图功能:从配置到实战案例全解析
华为·harmonyos
江拥羡橙6 小时前
【基础-判断】HarmonyOS提供了基础的应用加固安全能力,包括混淆、加密和代码签名能力
安全·华为·typescript·harmonyos
前端世界17 小时前
HarmonyOS 实战:用 @Observed + @ObjectLink 玩转多组件实时数据更新
华为·harmonyos