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