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 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