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