• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ContentSlot: Enabling Hybrid Development
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @sd-wu-->
5<!--Designer: @sunbees-->
6<!--Tester: @liuli0427-->
7<!--Adviser: @zhang_yixin13-->
8
9The **ContentSlot** component enables rendering and management of components created using C APIs on the native layer.
10
11With support for hybrid development, **ContentSlot** serves the recommended placeholder component when the container is an ArkTS component with child components created on the native side.
12
13## APIs
14
15### ArkTS-side APIs
16
17| Name | Description|
18| ------- | -------- |
19| ContentSlot(content: Content) | Container component for hybrid development. The **Content** object acts as the manager for **ContentSlot**, providing native-side APIs to register tree attachment and detachment callbacks and manage child components.|
20
21```ts
22abstract class Content {
23}
24```
25
26### Native-side APIs
27
28| Name| Description|
29| -------- | -------- |
30|OH_ArkUI_NodeContent_RegisterCallback(ArkUI_NodeContentHandle content, ArkUI_NodeContentCallback callback)|Registers an event with the **Content** manager.|
31|OH_ArkUI_NodeContentEvent_GetEventType(ArkUI_NodeContentEvent* event)|Obtains the type of the event triggered on the **Content**.|
32|OH_ArkUI_NodeContent_AddNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node)|Adds a child component to **Content**.|
33|OH_ArkUI_NodeContent_InsertNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node, int32_t position)|Inserts a child component into **Content**.|
34|OH_ArkUI_NodeContent_RemoveNode(ArkUI_NodeContentHandle content, ArkUI_NodeHandle node)|Removes a child component from **Content**.|
35|OH_ArkUI_GetNodeContentFromNapiValue(napi_env env, napi_value value, ArkUI_NodeContentHandle* content)|Obtains the pointer to **Content** in ArkTS from the native side.|
36|OH_ArkUI_NodeContentEvent_GetNodeContentHandle(ArkUI_NodeContentEvent* event)|Obtains the **Content** object that triggers the attach and detach events.|
37|OH_ArkUI_NodeContent_SetUserData(ArkUI_NodeContentHandle content, void* userData)|Sets the custom attributes on **Content**.|
38|OH_ArkUI_NodeContent_GetUserData(ArkUI_NodeContentHandle content)|Obtains the custom attributes from **Content**.|
39|typedef enum {<br>   NOTE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW = 0,<br>   NOTE_CONTENT_EVENT_ON_DETACH_FROM_WINDOW = 1,<br>} ArkUI_NodeContentEventType|Enumerates the event types on **Content**.|
40
41## Development and Implementation
42
43### ArkTS-side Implementation
44
45```ts
46import { nativeNode } from 'libNativeNode.so'; // Developer-implemented .so file.
47import { NodeContent } from '@kit.ArkUI';
48
49@Entry
50@Component
51struct Parent {
52  private nodeContent: Content = new NodeContent();
53
54  aboutToAppear() {
55    // Create a node through the C API and add it to the nodeContent manager.
56    nativeNode.createNativeNode(this.nodeContent);
57  }
58
59  build() {
60    Column() {
61      // Display the native components stored in the nodeContent manager.
62      ContentSlot(this.nodeContent)
63    }
64  }
65}
66```
67
68### Native-side Implementation
69For details about the basic development knowledge of Node-API, see [Getting Started with the NDK](../../napi/ndk-development-overview.md).
70
71This topic only describes how to implement the logic code related to **ContentSlot**. For details about how to create a component on the native side, see [NDK API Overview](../ndk-build-ui-overview.md).
72
73```c++
74#include "napi/native_api.h"
75#include "arkui/native_type.h"
76#include "arkui/native_node.h"
77#include "arkui/native_node_napi.h"
78#include "arkui/native_interface.h"
79#include "hilog/log.h"
80
81ArkUI_NodeContentHandle nodeContentHandle_ = nullptr;
82ArkUI_NativeNodeAPI_1 *nodeAPI;
83const unsigned int LOG_PRINT_DOMAIN = 0xFF00;
84
85// Create a 480 vp x 480 vp Column component with a red (0xFFFF0000) background on the native side. For details about how to create a node tree, see ArkUI C API documentation.
86ArkUI_NodeHandle CreateNodeHandle() {
87    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
88    ArkUI_NumberValue value[] = {480};
89    ArkUI_AttributeItem item{value, 1};
90    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
91    nodeAPI->setAttribute(column, NODE_HEIGHT, &item);
92    value[0].u32 = 0xFFFF0000;
93    nodeAPI->setAttribute(column, NODE_BACKGROUND_COLOR, &item);
94    return column;
95}
96
97// Native-side implementation of the ArkTS createNativeNode API.
98napi_value CreateNativeNode(napi_env env, napi_callback_info info) {
99    // Solve null pointer and out-of-bounds issues related to Node-API.
100    if ((env == nullptr) || (info == nullptr)) {
101        return nullptr;
102    }
103
104    size_t argc = 1;
105    napi_value args[1] = { nullptr };
106    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
107        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed");
108    }
109
110    if (argc != 1) {
111        return nullptr;
112    }
113
114    nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(
115        OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
116
117    // Point nodeContentHandle_ to a nodeContent object passed in from ArkTS.
118    OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_);
119
120    if (nodeAPI != nullptr) {
121        if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
122            ArkUI_NodeHandle component;
123            // Create a native-side component.
124            component = CreateNodeHandle();
125            // Add the component to the nodeContent manager.
126            OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, component);
127        }
128    }
129    return nullptr;
130}
131```
132
133### Native-side API Usage
134
135- **Registering Tree Events and Obtaining the Corresponding Content Object**
136
137  ```c++
138  auto nodeContentEvent = [](ArkUI_NodeContentEvent *event) {
139      ArkUI_NodeContentHandle content = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event);
140      // Additional logic required for different contents.
141      if (OH_ArkUINodeContentEvent_GetEventType(event) = NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) {
142          // Logic to be triggered when an attach event occurs on ContentSlot.
143      } else if (OH_ArkUINodeContentEvent_GetEventType(event) = NODE_CONTENT_EVENT_ON_DETACH_FROM_WINDOW) {
144          // Logic to be triggered when a detach event occurs on ContentSlot.
145      };
146  };
147  // Register an event with nodeContent.
148  OH_ArkUI_NodeContent_RegisterCallback(nodeContentHandle_, nodeContentEvent);
149  ```
150
151- **Adding Child Components**
152
153  ```c++
154  ArkUINodeHandle component;
155  component = CreateNodeHandle();
156  // Add the component to the nodeContent manager.
157  OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, component);
158  ```
159
160- **Inserting Child Components**
161
162  ```c++
163  ArkUINodeHandle component;
164  component = CreateNodeHandle();
165  // Insert a component into the specified position of the nodeContent manager.
166  OH_ArkUI_NodeContent_InsertNode(nodeContentHandle_, component, position);
167  ```
168
169- **Removing Child Components**
170
171  ```c++
172  // Remove a component from the nodeContent manager.
173  OH_ArkUI_NodeContent_RemoveNode(nodeContentHandle_, component);
174  ```
175
176- **Setting Custom Attributes**
177
178  ```c++
179  // Create the custom data to be defined.
180  void *userData = CreateUserData();
181  OH_ArkUI_NodeContent_SetUserData(nodeContentHandle_, userData);
182  ```
183
184- **Obtaining Custom Attributes**
185
186  ```
187  void *userData = OH_ArkUI_NodeContent_GetUserData(nodeContentHandle_);
188  ```
189