• Home
Name Date Size #Lines LOC

..--

AppScope/06-May-2025-3432

casesfeature/imperativedynamiclayouts/06-May-2025-768728

docs/06-May-2025-427410

entry/06-May-2025-545509

hvigor/06-May-2025-3736

.gitignoreD06-May-2025133 1212

README.mdD06-May-20254 KiB148114

build-profile.json5D06-May-20251.4 KiB6060

code-linter.json5D06-May-2025957 3434

hvigorfile.tsD06-May-2025842 215

oh-package.json5D06-May-2025808 2524

ohosTest.mdD06-May-2025645 107

README.md

1# 使用ArkUI的FrameNode扩展实现动态布局类框架
2
3### 介绍
4
5本示例是[使用ArkUI的FrameNode扩展实现动态布局类框架](./docs/imperative_dynamic_layouts.md)
6的示例代码,主要讲解如何使用ArkUI的FrameNode扩展实现动态布局类框架。
7
8### 效果图预览
9
10![](./docs/images/imperative_dynamic_layouts.gif)
11
12**使用说明**
13
141. 定义DSL用来描述UI。
152. 定义DSL解析逻辑,使用FrameNode来创建对应组件。
163. 使用NodeContainer组件占位,将创建的组件加载到页面中。
17
18### 实现思路
19
201. 定义DSL,DSL一般会使用JSON、XML等数据交换格式来描述UI,本案例使用JSON,详细代码请参考[foo.json](./casesfeature/imperativedynamiclayouts/src/main/ets/jsonpage/foo.json)。
21
22```json
23{
24  "type": "Column",
25  "css": {
26    "width": "100%"
27  },
28  "children": [
29    {
30      "type": "Row",
31      "css": {
32        "width": "100%",
33        "padding": {
34          "left": 15,
35          "right": 15
36        },
37        "margin": {
38          "top": 5,
39          "bottom": 5
40        },
41        ...
42      },
43      ...
44    },
45    ...
46  ]
47}
48```
49
502. 定义相应数据结构用于接收UI描述数据,详细代码参考[ImperativeView.ets](./casesfeature/imperativedynamiclayouts/src/main/ets/view/ImperativeView.ets)。
51
52```typescript
53class VM {
54  type?: string
55  content?: string
56  css?: ESObject
57  children?: VM[]
58  id?: string
59}
60```
61
623. 自定义DSL解析逻辑,且使用carouselNodes保存轮播图节点,方便后续操作节点更新,详细代码参考[ImperativeView.ets](./casesfeature/imperativedynamiclayouts/src/main/ets/view/ImperativeView.ets)。
63```typescript
64let carouselNodes: typeNode.Image[] = [];
65
66function FrameNodeFactory(vm: VM, context: UIContext): FrameNode | null {
67  ...
68  return null;
69}
70
71function setColumnNodeAttr(node: typeNode.Column, css: ESObject) {
72  ...
73}
74
75function setRowNodeAttr(node: typeNode.Row, css: ESObject) {
76  ...
77}
78```
79
804. 使用NodeContainer组件占位,将创建的组件加载到页面中,详细代码请参考[ImperativeView.ets](./casesfeature/imperativedynamiclayouts/src/main/ets/view/ImperativeView.ets)。
81```typescript
82class ImperativeController extends NodeController {
83  makeNode(uiContext: UIContext): FrameNode | null {
84    return FrameNodeFactory(data, uiContext);
85  }
86}
87
88@Entry
89@Component
90struct ImperativeView {
91  controller: ImperativeController = new ImperativeController();
92  build() {
93    Column() {
94      NodeContainer(this.controller)
95    }
96    .height('100%')
97    .width('100%')
98    .backgroundColor(Color.Black)
99  }
100}
101```
102
103### 高性能知识点
104
105使用ArkUI的FrameNode扩展,可以避免创建自定义组件对象和状态变量对象,也无需进行依赖收集,从而显著提升组件创建的速度,并且能更快的组件更新操作以及对组件树结构的直接控制。
106
107### 工程结构&模块类型
108
109   ```
110   imperativedynamiclayouts                           // har类型
111   |---jsonpage                                       // 存放描述UI的数据文件
112   |---|---foo.json                                   // 描述UI的数据
113   |---view                                           // 视图
114   |---|---ImperativeView.ets                         // 视频首页
115   ```
116
117### 参考资料
118
119[NodeContainer](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer)
120
121[NodeController](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/js-apis-arkui-nodeController.md)
122
123### 相关权限
124
125不涉及
126
127### 依赖
128
129不涉及
130
131### 约束与限制
132
1331. 本示例仅支持标准系统上运行。
134
1352. 本示例已适配API version 12版本SDK。
136
1373. 本示例需要使用DevEco Studio 5.0.0 Release及以上版本才可编译运行。
138
139### 下载
140
141如需单独下载本工程,执行如下命令:
142```bash
143git init
144git config core.sparsecheckout true
145echo /code/UI/ImperativeDynamicLayouts/ > .git/info/sparse-checkout
146git remote add origin https://gitee.com/openharmony/applications_app_samples.git
147git pull origin master
148```