1e41f4b71Sopenharmony_ci# Integrating with ArkTS Pages
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ci## Placeholder Components
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ciWhen building a UI with NDK APIs, you need to create placeholder components in the ArkTS page for mounting components created by the NDK APIs. The placeholder component type is [ContentSlot](../reference/apis-arkui/arkui-ts/ts-components-contentSlot.md), which can bind a **NodeContent** object. This object can be passed to the native side through the Node-API for mounting and displaying native components.
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ci- The usage of placeholder components is the same as other built-in ArkTS components.
9e41f4b71Sopenharmony_ci  ```ts
10e41f4b71Sopenharmony_ci  import { NodeContent } from '@kit.ArkUI';
11e41f4b71Sopenharmony_ci  
12e41f4b71Sopenharmony_ci  @Entry
13e41f4b71Sopenharmony_ci  @Component
14e41f4b71Sopenharmony_ci  struct Index {
15e41f4b71Sopenharmony_ci    // Initialize the NodeContent object.
16e41f4b71Sopenharmony_ci    private rootSlot = new NodeContent();
17e41f4b71Sopenharmony_ci    @State @Watch('changeNativeFlag') showNative: boolean = false;
18e41f4b71Sopenharmony_ci  
19e41f4b71Sopenharmony_ci    changeNativeFlag(): void {
20e41f4b71Sopenharmony_ci      if (this.showNative) {
21e41f4b71Sopenharmony_ci        // Pass the NodeContent object for the native side to create component mounting and display.
22e41f4b71Sopenharmony_ci        nativeNode.createNativeRoot(this.rootSlot)
23e41f4b71Sopenharmony_ci      } else {
24e41f4b71Sopenharmony_ci        // Destroy the NativeModule component.
25e41f4b71Sopenharmony_ci        nativeNode.destroyNativeRoot()
26e41f4b71Sopenharmony_ci      }
27e41f4b71Sopenharmony_ci    }
28e41f4b71Sopenharmony_ci  
29e41f4b71Sopenharmony_ci    build() {
30e41f4b71Sopenharmony_ci      Column() {
31e41f4b71Sopenharmony_ci        Button(this.showNative ? "HideNativeUI" : "ShowNativeUI").onClick(() => {
32e41f4b71Sopenharmony_ci          this.showNative = !this.showNative
33e41f4b71Sopenharmony_ci        })
34e41f4b71Sopenharmony_ci        Row() {
35e41f4b71Sopenharmony_ci          // Bind the NodeContent and ContentSlot placeholder component.
36e41f4b71Sopenharmony_ci          ContentSlot(this.rootSlot)
37e41f4b71Sopenharmony_ci        }.layoutWeight(1)
38e41f4b71Sopenharmony_ci      }
39e41f4b71Sopenharmony_ci      .width('100%')
40e41f4b71Sopenharmony_ci      .height('100%')
41e41f4b71Sopenharmony_ci    }
42e41f4b71Sopenharmony_ci  }
43e41f4b71Sopenharmony_ci  ```
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci- The placeholder component can be transformed into a mounting object on the native side through related APIs.
46e41f4b71Sopenharmony_ci  ```
47e41f4b71Sopenharmony_ci  ArkUI_NodeContentHandle contentHandle;
48e41f4b71Sopenharmony_ci  OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
49e41f4b71Sopenharmony_ci  ```
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci- The mounting object provides APIs for mounting and unmounting components.
52e41f4b71Sopenharmony_ci  ```
53e41f4b71Sopenharmony_ci  OH_ArkUI_NodeContent_AddNode(handle_, myNativeNode);
54e41f4b71Sopenharmony_ci  OH_ArkUI_NodeContent_RemoveNode(handle_, myNativeNode);
55e41f4b71Sopenharmony_ci  ```
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci
58e41f4b71Sopenharmony_ci## NDK Component Module
59e41f4b71Sopenharmony_ci
60e41f4b71Sopenharmony_ciThe UI component capabilities provided by the NDK, including component creation, tree operations, attribute setting, and event registration, are exposed using the function pointer structs (such as [ArkUI_NativeNodeAPI_1](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md)), which can be obtained through the [module query API](../reference/apis-arkui/_ark_u_i___native_module.md#oh_arkui_getmoduleinterface).
61e41f4b71Sopenharmony_ci
62e41f4b71Sopenharmony_ci```
63e41f4b71Sopenharmony_ciArkUI_NativeNodeAPI_1* arkUINativeNodeApi = nullptr;
64e41f4b71Sopenharmony_ciOH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, arkUINativeNodeApi);
65e41f4b71Sopenharmony_ci```
66e41f4b71Sopenharmony_ci
67e41f4b71Sopenharmony_ci
68e41f4b71Sopenharmony_ciAfter obtaining a function pointer struct, use the functions within the struct to perform UI component operations.
69e41f4b71Sopenharmony_ci
70e41f4b71Sopenharmony_ci
71e41f4b71Sopenharmony_ci- Create and destroy components.
72e41f4b71Sopenharmony_ci  ```
73e41f4b71Sopenharmony_ci  auto listNode = arkUINativeNodeApi->createNode(ARKUI_NODE_LIST);
74e41f4b71Sopenharmony_ci  arkUINativeNodeApi->disposeNode(listNode);
75e41f4b71Sopenharmony_ci  ```
76e41f4b71Sopenharmony_ci
77e41f4b71Sopenharmony_ci  You can query the range of components supported by the NDK API through the [ArkUI_NodeType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodetype) API.
78e41f4b71Sopenharmony_ci
79e41f4b71Sopenharmony_ci- Perform component tree operations.
80e41f4b71Sopenharmony_ci  ```
81e41f4b71Sopenharmony_ci  auto parent = arkUINativeNodeApi->createNode(ARKUI_NODE_STACK);
82e41f4b71Sopenharmony_ci  auto child = arkUINativeNodeApi->createNode(ARKUI_NODE_STACK);
83e41f4b71Sopenharmony_ci  arkUINativeNodeApi->addChild(parent, child);
84e41f4b71Sopenharmony_ci  arkUINativeNodeApi->removeChild(parent, child);
85e41f4b71Sopenharmony_ci  ```
86e41f4b71Sopenharmony_ci
87e41f4b71Sopenharmony_ci- Set attributes.
88e41f4b71Sopenharmony_ci  ```
89e41f4b71Sopenharmony_ci  auto stack = arkUINativeNodeApi->createNode(ARKUI_NODE_STACK);
90e41f4b71Sopenharmony_ci  ArkUI_NumberValue value[] = {{.f32 = 100}};
91e41f4b71Sopenharmony_ci  ArkUI_AttributeItem item = {value, 1};
92e41f4b71Sopenharmony_ci  arkUINativeNodeApi->setAttribute(stack, NODE_WIDTH, &item);
93e41f4b71Sopenharmony_ci  ArkUI_NumberValue value[] = {{.u32 = 0xff112233}};
94e41f4b71Sopenharmony_ci  ArkUI_AttributeItem item = {value, 1};
95e41f4b71Sopenharmony_ci  arkUINativeNodeApi->setAttribute(stack, NODE_BACKGROUND_COLOR, &item);
96e41f4b71Sopenharmony_ci  ```
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci  You can query the range of attributes supported by the NDK API through the[ArkUI_NodeAttributeType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeattributetype) API.
99e41f4b71Sopenharmony_ci
100e41f4b71Sopenharmony_ci- Register events.
101e41f4b71Sopenharmony_ci  ```
102e41f4b71Sopenharmony_ci  auto stack = arkUINativeNodeApi->createNode(ARKUI_NODE_STACK);
103e41f4b71Sopenharmony_ci  arkUINativeNodeApi->addNodeEventReceiver(stack, [](ArkUI_NodeEvent* event){
104e41f4b71Sopenharmony_ci      // process event
105e41f4b71Sopenharmony_ci  });
106e41f4b71Sopenharmony_ci  arkUINativeNodeApi->registerNodeEvent(stack, NODE_ON_CLICK, 0, nullptr);
107e41f4b71Sopenharmony_ci  ```
108e41f4b71Sopenharmony_ci
109e41f4b71Sopenharmony_ci  You can query the range of events supported by the NDK API through the [ArkUI_NodeEventType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeeventtype) API.
110e41f4b71Sopenharmony_ci
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci## Example
113e41f4b71Sopenharmony_ci
114e41f4b71Sopenharmony_ciThe following example demonstrates how to use **ContentSlot** to mount a native text list.
115e41f4b71Sopenharmony_ci
116e41f4b71Sopenharmony_ci**Figure 1** Native text list 
117e41f4b71Sopenharmony_ci
118e41f4b71Sopenharmony_ci![text_list](figures/text_list.gif)
119e41f4b71Sopenharmony_ci
120e41f4b71Sopenharmony_ci1. Declare a placeholder component for native page mounting on the ArkTS page, and notify the native side to create a text list when the page is created.
121e41f4b71Sopenharmony_ci   ```ts
122e41f4b71Sopenharmony_ci   import nativeNode from 'libentry.so';
123e41f4b71Sopenharmony_ci   import { NodeContent } from '@kit.ArkUI';
124e41f4b71Sopenharmony_ci   
125e41f4b71Sopenharmony_ci   @Entry
126e41f4b71Sopenharmony_ci   @Component
127e41f4b71Sopenharmony_ci   struct Index {
128e41f4b71Sopenharmony_ci     // Initialize the NodeContent object.
129e41f4b71Sopenharmony_ci     private rootSlot = new NodeContent();
130e41f4b71Sopenharmony_ci     @State @Watch('changeNativeFlag') showNative: boolean = false;
131e41f4b71Sopenharmony_ci   
132e41f4b71Sopenharmony_ci     changeNativeFlag(): void {
133e41f4b71Sopenharmony_ci       if (this.showNative) {
134e41f4b71Sopenharmony_ci         // Pass the NodeContent object for the native side to create component mounting and display.
135e41f4b71Sopenharmony_ci         nativeNode.createNativeRoot(this.rootSlot)
136e41f4b71Sopenharmony_ci       } else {
137e41f4b71Sopenharmony_ci         // Destroy the NativeModule component.
138e41f4b71Sopenharmony_ci         nativeNode.destroyNativeRoot()
139e41f4b71Sopenharmony_ci       }
140e41f4b71Sopenharmony_ci     }
141e41f4b71Sopenharmony_ci   
142e41f4b71Sopenharmony_ci     build() {
143e41f4b71Sopenharmony_ci       Column() {
144e41f4b71Sopenharmony_ci         Button(this.showNative ? "HideNativeUI" : "ShowNativeUI").onClick(() => {
145e41f4b71Sopenharmony_ci           this.showNative = !this.showNative
146e41f4b71Sopenharmony_ci         })
147e41f4b71Sopenharmony_ci         Row() {
148e41f4b71Sopenharmony_ci           // Bind the NodeContent and ContentSlot placeholder component.
149e41f4b71Sopenharmony_ci           ContentSlot(this.rootSlot)
150e41f4b71Sopenharmony_ci         }.layoutWeight(1)
151e41f4b71Sopenharmony_ci       }
152e41f4b71Sopenharmony_ci       .width('100%')
153e41f4b71Sopenharmony_ci       .height('100%')
154e41f4b71Sopenharmony_ci     }
155e41f4b71Sopenharmony_ci   }
156e41f4b71Sopenharmony_ci   ```
157e41f4b71Sopenharmony_ci
158e41f4b71Sopenharmony_ci2. Use the **Native** template to create a project, and provide a bridging method for the Node-API on the native side, implementing the **NativeNode** module APIs on the ArkTS side.
159e41f4b71Sopenharmony_ci   API declaration:
160e41f4b71Sopenharmony_ci   ```ts
161e41f4b71Sopenharmony_ci   // entry/src/main/cpp/types/libentry/Index.d.ts
162e41f4b71Sopenharmony_ci   
163e41f4b71Sopenharmony_ci   export const createNativeRoot: (content: Object) => void;
164e41f4b71Sopenharmony_ci   export const destroyNativeRoot: () => void;
165e41f4b71Sopenharmony_ci   ```
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci   Native implementation:
168e41f4b71Sopenharmony_ci   ```cpp
169e41f4b71Sopenharmony_ci   // entry/src/main/cpp/napi_init.cpp
170e41f4b71Sopenharmony_ci   
171e41f4b71Sopenharmony_ci   #include "NativeEntry.h"
172e41f4b71Sopenharmony_ci   #include "napi/native_api.h"
173e41f4b71Sopenharmony_ci   
174e41f4b71Sopenharmony_ci   EXTERN_C_START
175e41f4b71Sopenharmony_ci   static napi_value Init(napi_env env, napi_value exports) {
176e41f4b71Sopenharmony_ci       // Bind the native creation and destruction of components.
177e41f4b71Sopenharmony_ci       napi_property_descriptor desc[] = {
178e41f4b71Sopenharmony_ci           {"createNativeRoot", nullptr, NativeModule::CreateNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr},
179e41f4b71Sopenharmony_ci           {"destroyNativeRoot", nullptr, NativeModule::DestroyNativeRoot, nullptr, nullptr, nullptr, napi_default, nullptr}};
180e41f4b71Sopenharmony_ci       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
181e41f4b71Sopenharmony_ci       return exports;
182e41f4b71Sopenharmony_ci   }
183e41f4b71Sopenharmony_ci   EXTERN_C_END
184e41f4b71Sopenharmony_ci   
185e41f4b71Sopenharmony_ci   static napi_module demoModule = {
186e41f4b71Sopenharmony_ci       .nm_version = 1,
187e41f4b71Sopenharmony_ci       .nm_flags = 0,
188e41f4b71Sopenharmony_ci       .nm_filename = nullptr,
189e41f4b71Sopenharmony_ci       .nm_register_func = Init,
190e41f4b71Sopenharmony_ci       .nm_modname = "entry",
191e41f4b71Sopenharmony_ci       .nm_priv = ((void *)0),
192e41f4b71Sopenharmony_ci       .reserved = {0},
193e41f4b71Sopenharmony_ci   };
194e41f4b71Sopenharmony_ci   
195e41f4b71Sopenharmony_ci   extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
196e41f4b71Sopenharmony_ci   ```
197e41f4b71Sopenharmony_ci
198e41f4b71Sopenharmony_ci3. Create the native page in the **NativeEntry.h** file.
199e41f4b71Sopenharmony_ci   ```c
200e41f4b71Sopenharmony_ci   // NativeEntry.h
201e41f4b71Sopenharmony_ci   
202e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_NATIVEENTRY_H
203e41f4b71Sopenharmony_ci   #define MYAPPLICATION_NATIVEENTRY_H
204e41f4b71Sopenharmony_ci   
205e41f4b71Sopenharmony_ci   #include <js_native_api_types.h>
206e41f4b71Sopenharmony_ci   
207e41f4b71Sopenharmony_ci   namespace NativeModule {
208e41f4b71Sopenharmony_ci   
209e41f4b71Sopenharmony_ci   napi_value CreateNativeRoot(napi_env env, napi_callback_info info);
210e41f4b71Sopenharmony_ci   
211e41f4b71Sopenharmony_ci   napi_value DestroyNativeRoot(napi_env env, napi_callback_info info);
212e41f4b71Sopenharmony_ci   
213e41f4b71Sopenharmony_ci   // Manage the lifecycle and memory of the native component.
214e41f4b71Sopenharmony_ci   class NativeEntry {
215e41f4b71Sopenharmony_ci   public:
216e41f4b71Sopenharmony_ci       static NativeEntry *GetInstance() {
217e41f4b71Sopenharmony_ci           static NativeEntry nativeEntry;
218e41f4b71Sopenharmony_ci           return &nativeEntry;
219e41f4b71Sopenharmony_ci       }
220e41f4b71Sopenharmony_ci   
221e41f4b71Sopenharmony_ci       void SetContentHandle(ArkUI_NodeContentHandle handle) {
222e41f4b71Sopenharmony_ci           handle_ = handle;
223e41f4b71Sopenharmony_ci       }
224e41f4b71Sopenharmony_ci   
225e41f4b71Sopenharmony_ci       void SetRootNode(const std::shared_ptr<ArkUIBaseNode> &baseNode) {
226e41f4b71Sopenharmony_ci           root_ = baseNode;
227e41f4b71Sopenharmony_ci           // Add the native component to NodeContent for mounting and display.
228e41f4b71Sopenharmony_ci           OH_ArkUI_NodeContent_AddNode(handle_, root_->GetHandle());
229e41f4b71Sopenharmony_ci       }
230e41f4b71Sopenharmony_ci       void DisposeRootNode() {
231e41f4b71Sopenharmony_ci           // Unmount the component from NodeContent and destroy the native component.
232e41f4b71Sopenharmony_ci           OH_ArkUI_NodeContent_RemoveNode(handle_, root_->GetHandle());
233e41f4b71Sopenharmony_ci           root_.reset();
234e41f4b71Sopenharmony_ci       }
235e41f4b71Sopenharmony_ci   
236e41f4b71Sopenharmony_ci   private:
237e41f4b71Sopenharmony_ci       std::shared_ptr<ArkUIBaseNode> root_;
238e41f4b71Sopenharmony_ci       ArkUI_NodeContentHandle handle_;
239e41f4b71Sopenharmony_ci   };
240e41f4b71Sopenharmony_ci   
241e41f4b71Sopenharmony_ci   } // namespace NativeModule
242e41f4b71Sopenharmony_ci   
243e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_NATIVEENTRY_H
244e41f4b71Sopenharmony_ci   ```
245e41f4b71Sopenharmony_ci
246e41f4b71Sopenharmony_ci   Corresponding implementation file:
247e41f4b71Sopenharmony_ci   ```cpp
248e41f4b71Sopenharmony_ci   // NativeEntry.cpp
249e41f4b71Sopenharmony_ci   #include "NativeEntry.h"
250e41f4b71Sopenharmony_ci
251e41f4b71Sopenharmony_ci   #include <arkui/native_node_napi.h>
252e41f4b71Sopenharmony_ci   #include <hilog/log.h>
253e41f4b71Sopenharmony_ci   #include <js_native_api.h>
254e41f4b71Sopenharmony_ci   
255e41f4b71Sopenharmony_ci   namespace NativeModule {
256e41f4b71Sopenharmony_ci   
257e41f4b71Sopenharmony_ci   napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
258e41f4b71Sopenharmony_ci       size_t argc = 1;
259e41f4b71Sopenharmony_ci       napi_value args[1] = {nullptr};
260e41f4b71Sopenharmony_ci   
261e41f4b71Sopenharmony_ci       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
262e41f4b71Sopenharmony_ci   
263e41f4b71Sopenharmony_ci       // Obtain NodeContent.
264e41f4b71Sopenharmony_ci       ArkUI_NodeContentHandle contentHandle;
265e41f4b71Sopenharmony_ci       OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
266e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->SetContentHandle(contentHandle);
267e41f4b71Sopenharmony_ci   
268e41f4b71Sopenharmony_ci       // Create a text list.
269e41f4b71Sopenharmony_ci       auto list = CreateTextListExample();
270e41f4b71Sopenharmony_ci   
271e41f4b71Sopenharmony_ci       // Keep the native side object in the management class to maintain its lifecycle.
272e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->SetRootNode(list);
273e41f4b71Sopenharmony_ci       return nullptr;
274e41f4b71Sopenharmony_ci   }
275e41f4b71Sopenharmony_ci   
276e41f4b71Sopenharmony_ci   napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
277e41f4b71Sopenharmony_ci       // Release the native side object from the management class.
278e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->DisposeRootNode();
279e41f4b71Sopenharmony_ci       return nullptr;
280e41f4b71Sopenharmony_ci   }
281e41f4b71Sopenharmony_ci   
282e41f4b71Sopenharmony_ci   } // namespace NativeModule
283e41f4b71Sopenharmony_ci   ```
284e41f4b71Sopenharmony_ci
285e41f4b71Sopenharmony_ci   When using the C APIs provided by the NDK, you need to add a reference to **libace_ndk.z.so** in the **CMakeLists.txt** file, as shown below. Here, **entry** is the name of the dynamic library exported by the project, such as the default name **libentry.so** used in this example.
286e41f4b71Sopenharmony_ci   ```
287e41f4b71Sopenharmony_ci   target_link_libraries(entry PUBLIC libace_napi.z.so libace_ndk.z.so)
288e41f4b71Sopenharmony_ci   ```
289e41f4b71Sopenharmony_ci
290e41f4b71Sopenharmony_ci4. Since the NDK provides C APIs, to simplify programming and project management in an object-oriented manner, it is recommended that you use C++ for secondary encapsulation. The following example shows the encapsulation classes required for the list and text components on the example page.
291e41f4b71Sopenharmony_ci   (1) Obtain the entry module of ArkUI in the NDK API [ArkUI_NativeNodeAPI_1](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md), which provides a series of function pointers for component creation, tree construction, attribute setting, and event registration.
292e41f4b71Sopenharmony_ci   ```c
293e41f4b71Sopenharmony_ci   // NativeModule.h
294e41f4b71Sopenharmony_ci   // Provide encapsulated APIs for obtaining ArkUI modules on the native side.
295e41f4b71Sopenharmony_ci   
296e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_NATIVEMODULE_H
297e41f4b71Sopenharmony_ci   #define MYAPPLICATION_NATIVEMODULE_H
298e41f4b71Sopenharmony_ci   
299e41f4b71Sopenharmony_ci   #include <arkui/native_node.h>
300e41f4b71Sopenharmony_ci   #include <functional>
301e41f4b71Sopenharmony_ci   #include <cassert>
302e41f4b71Sopenharmony_ci   
303e41f4b71Sopenharmony_ci   #include <arkui/native_interface.h>
304e41f4b71Sopenharmony_ci   
305e41f4b71Sopenharmony_ci   namespace NativeModule {
306e41f4b71Sopenharmony_ci   
307e41f4b71Sopenharmony_ci   class NativeModuleInstance {
308e41f4b71Sopenharmony_ci   public:
309e41f4b71Sopenharmony_ci       static NativeModuleInstance *GetInstance() {
310e41f4b71Sopenharmony_ci           static NativeModuleInstance instance;
311e41f4b71Sopenharmony_ci           return &instance;
312e41f4b71Sopenharmony_ci       }
313e41f4b71Sopenharmony_ci   
314e41f4b71Sopenharmony_ci       NativeModuleInstance() {
315e41f4b71Sopenharmony_ci           // Obtain the function pointer struct of the NDK API for subsequent operations.
316e41f4b71Sopenharmony_ci           OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, arkUINativeNodeApi_);
317e41f4b71Sopenharmony_ci           assert(arkUINativeNodeApi_);
318e41f4b71Sopenharmony_ci       }
319e41f4b71Sopenharmony_ci       // Expose it for use by other modules.
320e41f4b71Sopenharmony_ci       ArkUI_NativeNodeAPI_1 *GetNativeNodeAPI() { return arkUINativeNodeApi_; }
321e41f4b71Sopenharmony_ci   
322e41f4b71Sopenharmony_ci   private:
323e41f4b71Sopenharmony_ci       ArkUI_NativeNodeAPI_1 *arkUINativeNodeApi_ = nullptr;
324e41f4b71Sopenharmony_ci   };
325e41f4b71Sopenharmony_ci   
326e41f4b71Sopenharmony_ci   } // namespace NativeModule
327e41f4b71Sopenharmony_ci   
328e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_NATIVEMODULE_H
329e41f4b71Sopenharmony_ci   ```
330e41f4b71Sopenharmony_ci
331e41f4b71Sopenharmony_ci   (2) Provide base class objects for list and text components to encapsulate common properties and events.
332e41f4b71Sopenharmony_ci
333e41f4b71Sopenharmony_ci   ```c
334e41f4b71Sopenharmony_ci   // ArkUIBaseNode.h
335e41f4b71Sopenharmony_ci   // Provide a base class for component tree operations.
336e41f4b71Sopenharmony_ci   
337e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_ARKUIBASENODE_H
338e41f4b71Sopenharmony_ci   #define MYAPPLICATION_ARKUIBASENODE_H
339e41f4b71Sopenharmony_ci   
340e41f4b71Sopenharmony_ci   #include <arkui/native_type.h>
341e41f4b71Sopenharmony_ci   #include <list>
342e41f4b71Sopenharmony_ci   #include <memory>
343e41f4b71Sopenharmony_ci   
344e41f4b71Sopenharmony_ci   #include "NativeModule.h"
345e41f4b71Sopenharmony_ci   
346e41f4b71Sopenharmony_ci   namespace NativeModule {
347e41f4b71Sopenharmony_ci   
348e41f4b71Sopenharmony_ci   class ArkUIBaseNode {
349e41f4b71Sopenharmony_ci   public:
350e41f4b71Sopenharmony_ci       explicit ArkUIBaseNode(ArkUI_NodeHandle handle)
351e41f4b71Sopenharmony_ci           : handle_(handle), nativeModule_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()) {}
352e41f4b71Sopenharmony_ci   
353e41f4b71Sopenharmony_ci       virtual ~ArkUIBaseNode() {
354e41f4b71Sopenharmony_ci           // Encapsulate the destructor to implement child node removal functionality.
355e41f4b71Sopenharmony_ci           if (!children_.empty()) {
356e41f4b71Sopenharmony_ci               for (const auto& child : children_) {
357e41f4b71Sopenharmony_ci                   nativeModule_->removeChild(handle_, child->GetHandle());
358e41f4b71Sopenharmony_ci               }
359e41f4b71Sopenharmony_ci               children_.clear();
360e41f4b71Sopenharmony_ci           }
361e41f4b71Sopenharmony_ci           // Encapsulate the destructor to uniformly recover node resources.
362e41f4b71Sopenharmony_ci           nativeModule_->disposeNode(handle_);
363e41f4b71Sopenharmony_ci       }
364e41f4b71Sopenharmony_ci   
365e41f4b71Sopenharmony_ci       void AddChild(const std::shared_ptr<ArkUIBaseNode> &child) {
366e41f4b71Sopenharmony_ci           children_.emplace_back(child);
367e41f4b71Sopenharmony_ci           OnAddChild(child);
368e41f4b71Sopenharmony_ci       }
369e41f4b71Sopenharmony_ci   
370e41f4b71Sopenharmony_ci       void RemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) {
371e41f4b71Sopenharmony_ci           children_.remove(child);
372e41f4b71Sopenharmony_ci           OnRemoveChild(child);
373e41f4b71Sopenharmony_ci       }
374e41f4b71Sopenharmony_ci   
375e41f4b71Sopenharmony_ci       void InsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) {
376e41f4b71Sopenharmony_ci           if (index >= children_.size()) {
377e41f4b71Sopenharmony_ci               AddChild(child);
378e41f4b71Sopenharmony_ci           } else {
379e41f4b71Sopenharmony_ci               auto iter = children_.begin();
380e41f4b71Sopenharmony_ci               std::advance(iter, index);
381e41f4b71Sopenharmony_ci               children_.insert(iter, child);
382e41f4b71Sopenharmony_ci               OnInsertChild(child, index);
383e41f4b71Sopenharmony_ci           }
384e41f4b71Sopenharmony_ci       }
385e41f4b71Sopenharmony_ci   
386e41f4b71Sopenharmony_ci       ArkUI_NodeHandle GetHandle() const { return handle_; }
387e41f4b71Sopenharmony_ci   
388e41f4b71Sopenharmony_ci   protected:
389e41f4b71Sopenharmony_ci       // Override the following functions in subclasses that act as parent containers to implement component mounting and unmounting.
390e41f4b71Sopenharmony_ci       virtual void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) {}
391e41f4b71Sopenharmony_ci       virtual void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) {}
392e41f4b71Sopenharmony_ci       virtual void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) {}
393e41f4b71Sopenharmony_ci   
394e41f4b71Sopenharmony_ci       ArkUI_NodeHandle handle_;
395e41f4b71Sopenharmony_ci       ArkUI_NativeNodeAPI_1 *nativeModule_ = nullptr;
396e41f4b71Sopenharmony_ci   
397e41f4b71Sopenharmony_ci   private:
398e41f4b71Sopenharmony_ci       std::list<std::shared_ptr<ArkUIBaseNode>> children_;
399e41f4b71Sopenharmony_ci   };
400e41f4b71Sopenharmony_ci   } // namespace NativeModule
401e41f4b71Sopenharmony_ci   
402e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_ARKUIBASENODE_H
403e41f4b71Sopenharmony_ci   ```
404e41f4b71Sopenharmony_ci
405e41f4b71Sopenharmony_ci   ```c
406e41f4b71Sopenharmony_ci   // ArkUINode.h
407e41f4b71Sopenharmony_ci   // Provide encapsulation of common properties and events.
408e41f4b71Sopenharmony_ci   
409e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_ARKUINODE_H
410e41f4b71Sopenharmony_ci   #define MYAPPLICATION_ARKUINODE_H
411e41f4b71Sopenharmony_ci   
412e41f4b71Sopenharmony_ci   #include "ArkUIBaseNode.h"
413e41f4b71Sopenharmony_ci   #include "NativeModule.h"
414e41f4b71Sopenharmony_ci   #include <arkui/native_node.h>
415e41f4b71Sopenharmony_ci   #include <arkui/native_type.h>
416e41f4b71Sopenharmony_ci   
417e41f4b71Sopenharmony_ci   namespace NativeModule {
418e41f4b71Sopenharmony_ci   
419e41f4b71Sopenharmony_ci   class ArkUINode : public ArkUIBaseNode {
420e41f4b71Sopenharmony_ci   public:
421e41f4b71Sopenharmony_ci       explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle) {}
422e41f4b71Sopenharmony_ci   
423e41f4b71Sopenharmony_ci       ~ArkUINode() override {}
424e41f4b71Sopenharmony_ci   
425e41f4b71Sopenharmony_ci       // Encapsulate the common property call related to the NDK.
426e41f4b71Sopenharmony_ci       void SetWidth(float width) {
427e41f4b71Sopenharmony_ci           assert(handle_);
428e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.f32 = width}};
429e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
430e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_WIDTH, &item);
431e41f4b71Sopenharmony_ci       }
432e41f4b71Sopenharmony_ci       void SetPercentWidth(float percent) {
433e41f4b71Sopenharmony_ci           assert(handle_);
434e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.f32 = percent}};
435e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
436e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item);
437e41f4b71Sopenharmony_ci       }
438e41f4b71Sopenharmony_ci       void SetHeight(float height) {
439e41f4b71Sopenharmony_ci           assert(handle_);
440e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.f32 = height}};
441e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
442e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item);
443e41f4b71Sopenharmony_ci       }
444e41f4b71Sopenharmony_ci       void SetPercentHeight(float percent) {
445e41f4b71Sopenharmony_ci           assert(handle_);
446e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.f32 = percent}};
447e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
448e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item);
449e41f4b71Sopenharmony_ci       }
450e41f4b71Sopenharmony_ci       void SetBackgroundColor(uint32_t color) {
451e41f4b71Sopenharmony_ci           assert(handle_);
452e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.u32 = color}};
453e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
454e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item);
455e41f4b71Sopenharmony_ci       }
456e41f4b71Sopenharmony_ci   
457e41f4b71Sopenharmony_ci   protected:
458e41f4b71Sopenharmony_ci       // Implement class docking for component tree operations.
459e41f4b71Sopenharmony_ci       void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
460e41f4b71Sopenharmony_ci           nativeModule_->addChild(handle_, child->GetHandle());
461e41f4b71Sopenharmony_ci       }
462e41f4b71Sopenharmony_ci       void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
463e41f4b71Sopenharmony_ci           nativeModule_->removeChild(handle_, child->GetHandle());
464e41f4b71Sopenharmony_ci       }
465e41f4b71Sopenharmony_ci       void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override {
466e41f4b71Sopenharmony_ci           nativeModule_->insertChildAt(handle_, child->GetHandle(), index);
467e41f4b71Sopenharmony_ci       }
468e41f4b71Sopenharmony_ci   };
469e41f4b71Sopenharmony_ci   } // namespace NativeModule
470e41f4b71Sopenharmony_ci   
471e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_ARKUINODE_H
472e41f4b71Sopenharmony_ci   ```
473e41f4b71Sopenharmony_ci
474e41f4b71Sopenharmony_ci   (3) Implement the list component.
475e41f4b71Sopenharmony_ci
476e41f4b71Sopenharmony_ci   ```c
477e41f4b71Sopenharmony_ci   // ArkUIListNode.h
478e41f4b71Sopenharmony_ci   // Provide encapsulation for the list component. 
479e41f4b71Sopenharmony_ci   
480e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_ARKUILISTNODE_H
481e41f4b71Sopenharmony_ci   #define MYAPPLICATION_ARKUILISTNODE_H
482e41f4b71Sopenharmony_ci   
483e41f4b71Sopenharmony_ci   #include "ArkUINode.h"
484e41f4b71Sopenharmony_ci   
485e41f4b71Sopenharmony_ci   namespace NativeModule {
486e41f4b71Sopenharmony_ci   class ArkUIListNode : public ArkUINode {
487e41f4b71Sopenharmony_ci   public:
488e41f4b71Sopenharmony_ci       ArkUIListNode()
489e41f4b71Sopenharmony_ci           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {} // Create the ArkUI list component.
490e41f4b71Sopenharmony_ci   
491e41f4b71Sopenharmony_ci       ~ArkUIListNode() override {} 
492e41f4b71Sopenharmony_ci       // List component's NDK API encapsulation for properties.
493e41f4b71Sopenharmony_ci       void SetScrollBarState(bool isShow) {
494e41f4b71Sopenharmony_ci           assert(handle_);
495e41f4b71Sopenharmony_ci           ArkUI_ScrollBarDisplayMode displayMode =
496e41f4b71Sopenharmony_ci               isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF;
497e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.i32 = displayMode}};
498e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
499e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item);
500e41f4b71Sopenharmony_ci       }
501e41f4b71Sopenharmony_ci   };
502e41f4b71Sopenharmony_ci   } // namespace NativeModule
503e41f4b71Sopenharmony_ci   
504e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_ARKUILISTNODE_H
505e41f4b71Sopenharmony_ci   ```
506e41f4b71Sopenharmony_ci
507e41f4b71Sopenharmony_ci   (4) Implement the list item component.
508e41f4b71Sopenharmony_ci
509e41f4b71Sopenharmony_ci   ```c
510e41f4b71Sopenharmony_ci   // ArkUIListItemNode.h
511e41f4b71Sopenharmony_ci   // Provide an encapsulation class for list items
512e41f4b71Sopenharmony_ci   
513e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_ARKUISTACKNODE_H
514e41f4b71Sopenharmony_ci   #define MYAPPLICATION_ARKUISTACKNODE_H
515e41f4b71Sopenharmony_ci   
516e41f4b71Sopenharmony_ci   #include "ArkUINode.h"
517e41f4b71Sopenharmony_ci   
518e41f4b71Sopenharmony_ci   namespace NativeModule {
519e41f4b71Sopenharmony_ci   class ArkUIListItemNode : public ArkUINode {
520e41f4b71Sopenharmony_ci   public:
521e41f4b71Sopenharmony_ci       ArkUIListItemNode()
522e41f4b71Sopenharmony_ci           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST_ITEM)) {}
523e41f4b71Sopenharmony_ci   };
524e41f4b71Sopenharmony_ci   } // namespace NativeModule
525e41f4b71Sopenharmony_ci   
526e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_ARKUISTACKNODE_H
527e41f4b71Sopenharmony_ci   ```
528e41f4b71Sopenharmony_ci
529e41f4b71Sopenharmony_ci   (5) Implement the text component.
530e41f4b71Sopenharmony_ci
531e41f4b71Sopenharmony_ci   ```c
532e41f4b71Sopenharmony_ci   // ArkUITextNode.h
533e41f4b71Sopenharmony_ci   // Implement an encapsulation class for the text component.
534e41f4b71Sopenharmony_ci   
535e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_ARKUITEXTNODE_H
536e41f4b71Sopenharmony_ci   #define MYAPPLICATION_ARKUITEXTNODE_H
537e41f4b71Sopenharmony_ci   
538e41f4b71Sopenharmony_ci   #include "ArkUINode.h"
539e41f4b71Sopenharmony_ci   
540e41f4b71Sopenharmony_ci   #include <string>
541e41f4b71Sopenharmony_ci   
542e41f4b71Sopenharmony_ci   namespace NativeModule {
543e41f4b71Sopenharmony_ci   class ArkUITextNode : public ArkUINode {
544e41f4b71Sopenharmony_ci   public:
545e41f4b71Sopenharmony_ci       ArkUITextNode()
546e41f4b71Sopenharmony_ci           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_TEXT)) {}
547e41f4b71Sopenharmony_ci       // Text component's NDK API encapsulation for properties.
548e41f4b71Sopenharmony_ci       void SetFontSize(float fontSize) {
549e41f4b71Sopenharmony_ci           assert(handle_);
550e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.f32 = fontSize}};
551e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
552e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_FONT_SIZE, &item);
553e41f4b71Sopenharmony_ci       }
554e41f4b71Sopenharmony_ci       void SetFontColor(uint32_t color) {
555e41f4b71Sopenharmony_ci           assert(handle_);
556e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.u32 = color}};
557e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
558e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_FONT_COLOR, &item);
559e41f4b71Sopenharmony_ci       }
560e41f4b71Sopenharmony_ci       void SetTextContent(const std::string &content) {
561e41f4b71Sopenharmony_ci           assert(handle_);
562e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {nullptr, 0, content.c_str()};
563e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_TEXT_CONTENT, &item);
564e41f4b71Sopenharmony_ci       }
565e41f4b71Sopenharmony_ci       void SetTextAlign(ArkUI_TextAlignment align) {
566e41f4b71Sopenharmony_ci           assert(handle_);
567e41f4b71Sopenharmony_ci           ArkUI_NumberValue value[] = {{.i32 = align}};
568e41f4b71Sopenharmony_ci           ArkUI_AttributeItem item = {value, 1};
569e41f4b71Sopenharmony_ci           nativeModule_->setAttribute(handle_, NODE_TEXT_ALIGN, &item);
570e41f4b71Sopenharmony_ci       }
571e41f4b71Sopenharmony_ci   };
572e41f4b71Sopenharmony_ci   } // namespace NativeModule
573e41f4b71Sopenharmony_ci   
574e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_ARKUITEXTNODE_H
575e41f4b71Sopenharmony_ci   ```
576e41f4b71Sopenharmony_ci
577e41f4b71Sopenharmony_ci5. Complete the **CreateTextListExample** function from step 3 to create and mount the display of the native text list.
578e41f4b71Sopenharmony_ci   ```c
579e41f4b71Sopenharmony_ci   // NativeEntry.h
580e41f4b71Sopenharmony_ci   // Define custom NDK API entry functions.
581e41f4b71Sopenharmony_ci   
582e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
583e41f4b71Sopenharmony_ci   #define MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
584e41f4b71Sopenharmony_ci   
585e41f4b71Sopenharmony_ci   #include "ArkUIBaseNode.h"
586e41f4b71Sopenharmony_ci   #include "ArkUIListItemNode.h"
587e41f4b71Sopenharmony_ci   #include "ArkUIListNode.h"
588e41f4b71Sopenharmony_ci   #include "ArkUITextNode.h"
589e41f4b71Sopenharmony_ci   #include <hilog/log.h>
590e41f4b71Sopenharmony_ci   
591e41f4b71Sopenharmony_ci   namespace NativeModule {
592e41f4b71Sopenharmony_ci   
593e41f4b71Sopenharmony_ci   std::shared_ptr<ArkUIBaseNode> CreateTextListExample() {
594e41f4b71Sopenharmony_ci       // Create components and mount them.
595e41f4b71Sopenharmony_ci       // 1: Use smart pointers to create a List component.
596e41f4b71Sopenharmony_ci       auto list = std::make_shared<ArkUIListNode>();
597e41f4b71Sopenharmony_ci       list->SetPercentWidth(1);
598e41f4b71Sopenharmony_ci       list->SetPercentHeight(1);
599e41f4b71Sopenharmony_ci       // 2: Create a ListItem child component and mount it to the List component.
600e41f4b71Sopenharmony_ci       for (int32_t i = 0; i < 30; ++i) {
601e41f4b71Sopenharmony_ci           auto listItem = std::make_shared<ArkUIListItemNode>();
602e41f4b71Sopenharmony_ci           auto textNode = std::make_shared<ArkUITextNode>();
603e41f4b71Sopenharmony_ci           textNode->SetTextContent(std::to_string(i));
604e41f4b71Sopenharmony_ci           textNode->SetFontSize(16);
605e41f4b71Sopenharmony_ci           textNode->SetPercentWidth(1);
606e41f4b71Sopenharmony_ci           textNode->SetHeight(100);
607e41f4b71Sopenharmony_ci           textNode->SetBackgroundColor(0xFFfffacd);
608e41f4b71Sopenharmony_ci           textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
609e41f4b71Sopenharmony_ci           listItem->AddChild(textNode);
610e41f4b71Sopenharmony_ci           list->AddChild(listItem);
611e41f4b71Sopenharmony_ci       }
612e41f4b71Sopenharmony_ci       return list;
613e41f4b71Sopenharmony_ci   }
614e41f4b71Sopenharmony_ci   } // namespace NativeModule
615e41f4b71Sopenharmony_ci   
616e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
617e41f4b71Sopenharmony_ci   ```
618