• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ContentSlot:混合开发
2
3用于渲染并管理Native层使用C-API创建的组件。
4
5支持混合模式开发,当容器是ArkTS组件,子组件在Native侧创建时,推荐使用ContentSlot占位组件。
6
7## 接口
8
9### ContentSlot组件接口
10
11```ts
12ContentSlot(content: Content); // 当前开发者需要使用ArkUI提供的NodeContent作为管理器
13```
14
15| 参数名  | 类型 | 必填 | 参数描述                                                     |
16| ------- | -------- | ---- | ------------------------------------------------------------ |
17| content | Content  | 是   | Content作为ContentSlot的管理器,通过Native侧提供的接口,可以注册并触发ContentSlot的上下树事件回调以及管理ContentSlot的子组件。 |
18
19```ts
20abstract class Content {
21}
22```
23
24### ContentSlotInterface
25
26(content: Content): ContentSlotAttribute;
27
28当内容添加到占位符组件时调用
29
30**系统能力:** SystemCapability.ArkUI.ArkUI.Full
31
32**参数:**
33
34| 参数名  | 类型 | 必填 | 参数描述                                                     |
35| ------- | -------- | ---- | ------------------------------------------------------------ |
36| content | Content  | 是   | Content作为ContentSlot的管理器,通过Native侧提供的接口,可以注册并触发ContentSlot的上下树事件回调以及管理ContentSlot的子组件。 |
37
38### ContentSlotAttribute
39
40定义ContentSlot属性,以防止不正确的递归使用ContentSlot
41
42**系统能力:** SystemCapability.ArkUI.ArkUI.Full
43
44### Native侧接口
45
46| 接口名 | 描述 |
47| -------- | -------- |
48|OH_ArkUI_NodeContent_RegisterCallback(ArkUI_NodeContentHandle content, ArkUI_NodeContentCallback callback)|向管理器Content上注册事件。|
49|OH_ArkUI_NodeContentEvent_GetEventType(ArkUI_NodeContentEvent* event)|获取Content上触发的事件类型。|
50|OH_ArkUI_NodeContent_AddNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node)|在Content上添加子组件。|
51|OH_ArkUI_NodeContent_InsertNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node, int32_t position)|在Content上插入子组件。|
52|OH_ArkUI_NodeContent_RemoveNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node)|在Content上移除子组件。|
53|OH_ArkUI_GetNodeContentFromNapiValue(napi_env env, napi_value value, ArkUI_NodeContentHandle* content)|在Native侧获取ArkTS侧Content指针。|
54|OH_ArkUI_NodeContentEvent_GetNodeContentHandle(ArkUI_NodeContentEvent* event)|获取触发上下树事件的Content对象。|
55|OH_ArkUI_NodeContent_SetUserData(ArkUI_NodeContentHandle content, void* userData)|在Content上设置用户自定义属性。|
56|OH_ArkUI_NodeContent_GetUserData(ArkUI_NodeContentHandle content)|在Content上获取用户自定义属性。|
57|typedef enum {<br>   NOTE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW = 0,<br>   NOTE_CONTENT_EVENT_ON_DETACH_FROM_WINDOW = 1,<br>} ArkUI_NodeContentEventType|Content上会触发的上树和下树两种事件类型。|
58
59## 开发实现
60
61### ArkTS侧代码实现
62
63```ts
64import { nativeNode } from 'libNativeNode.so' // 开发者自己实现的so
65import { NodeContent } from '@kit.ArkUI'
66
67@Component
68struct Parent {
69    private nodeContent: Content = new NodeContent();
70
71    aboutToAppear() {
72        // 通过C-API创建节点,并添加到管理器nodeContent上
73        nativeNode.createNativeNode(this.nodeContent);
74    }
75
76    build() {
77        Column() {
78            // 显示nodeContent管理器里存放的Native侧的组件
79            ContentSlot(this.nodeContent)
80        }
81    }
82}
83```
84
85### Native侧代码实现
86Napi的基础开发知识请查看以下文档:[开发导读](../napi/ndk-development-overview.md)。
87
88本章节仅描述实现ContentSlot相关逻辑代码。创建C侧组件,具体请查看[使用NDK接口构建UI](../ui/ndk-build-ui-overview.md)。
89
90```c++
91#include "napi/native_api.h"
92#include "arkui/native_type.h"
93#include "arkui/native_node.h"
94#include "arkui/native_node_napi.h"
95#include "arkui/native_interface.h"
96#include "hilog/log.h"
97
98ArkUI_NodeContentHandle nodeContentHandle_ = nullptr;
99ArkUI_NativeNodeAPI_1 *nodeAPI;
100const unsigned int LOG_PRINT_DOMAIN = 0xFF00;
101
102// Manager为应用定义的NativeNode管理类
103napi_value Manager::CreateNativeNode(napi_env env, napi_callback_info info) {
104    // napi相关处理空指针&数据越界等问题
105    if ((env == nullptr) || (info == nullptr)) {
106        return nullptr;
107    }
108
109    size_t argc = 1;
110    napi_value args[1] = { nullptr };
111    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
112        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed");
113    }
114
115    if (argc != 1) {
116        return nullptr;
117    }
118
119    nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(
120        OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNode_API_1"));
121
122    // 将nodeContentHandle_指向ArkTS侧传入的nodeContent
123    OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_);
124
125    if (nodeAPI != nullptr) {
126        if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
127            ArkUI_NodeHandle component;
128            // 创建C侧组件,具体请查看ArkUI api文档的Capi章节
129            component = CreateNodeHandle();
130            // 将组件添加到nodeContent管理器中
131            OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, component);
132        }
133    }
134}
135```
136
137#### 注册上下树事件,并通过事件获取对应的Content对象
138
139```c++
140auto nodeContentEvent = [](ArkUI_NodeContentEvent *event) {
141    ArkUI_NodeContentHandle content = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event);
142    // 针对不同content需要额外做的逻辑
143    if (OH_ArkUINodeContentEvent_GetEventType(event) = NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) {
144        // ContentSlot上树时需要触发的逻辑
145    } else if (OH_ArkUINodeContentEvent_GetEventType(event) = NODE_CONTENT_EVENT_ON_DETACH_FROM_WINDOW) {
146        // ContentSlot下树时需要触发的逻辑
147    };
148};
149// 将该事件注册到nodeContent上
150OH_ArkUI_NodeContent_RegisterCallback(nodeContentHandle_, nodeContentEvent);
151```
152
153#### 添加子组件
154
155```c++
156ArkUINodeHandle component;
157component = CreateNodeHandle();
158// 将组件添加到nodeContent管理器中
159OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, component);
160```
161
162#### 插入子组件
163
164```c++
165ArkUINodeHandle component;
166component = CreateNodeHandle();
167// 将组件插入nodeContent管理器对应位置
168OH_ArkUI_NodeContent_InsertNode(nodeContentHandle_, component, position);
169```
170
171#### 删除子组件
172
173```c++
174// 在nodeContent中移除对应组件
175OH_ArkUI_NodeContent_RemoveNode(nodeContentHandle_, component);
176```
177
178#### 设置自定义属性
179
180```c++
181// 创建需要定义的自定义数据
182void *userData = CreateUserData();
183OH_ArkUI_NodeContent_SetUserData(nodeContentHandle_, userData);
184```
185
186#### 获取自定义属性
187
188```
189void *userData = OH_ArkUI_NodeContent_GetUserData(nodeContentHandle_);
190```
191