1e41f4b71Sopenharmony_ci# Building Custom Components
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciThe ArkUI development framework provides capabilities for creating custom UI components through NDK APIs, including custom measurement, layout, and drawing. You can integrate into ArkUI's layout and rendering process by registering custom callback events using the [registerNodeCustomEvent](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodecustomevent) function and adding custom event listeners for components with the [addNodeCustomEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addnodecustomeventreceiver) function. The logic for custom measurement, layout, and drawing is handled within the callback functions of these listeners.
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci> **NOTE**
8e41f4b71Sopenharmony_ci>
9e41f4b71Sopenharmony_ci> - Custom component event registration requires [addNodeCustomEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addnodecustomeventreceiver) to declare the listener registration and registerNodeCustomEvent](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodecustomevent) to declare the required custom event types; listeners can only listen to declared events.
10e41f4b71Sopenharmony_ci> 
11e41f4b71Sopenharmony_ci> - IPay attention to the logic of event deregistration, such as calling [removeNodeCustomEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#removenodecustomeventreceiver) to remove the event listener before the component is destroyed, and [unregisterNodeCustomEvent](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#unregisternodecustomevent) to notify the ArkUI framework that the custom component events that have been listened to are no longer needed.
12e41f4b71Sopenharmony_ci> 
13e41f4b71Sopenharmony_ci> - [addNodeCustomEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addnodecustomeventreceiver) can add multiple function pointers, each of which is triggered when the corresponding event occurs. To remove a listener, the corresponding [removeNodeCustomEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#removenodecustomeventreceiver) function must be called with the exact function pointer used for adding the listener.
14e41f4b71Sopenharmony_ci> 
15e41f4b71Sopenharmony_ci> - [registerNodeCustomEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodecustomeventreceiver) is a global event listener function. Unlike [addNodeCustomEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addnodecustomeventreceiver), **registerNodeCustomEventReceiver** can listen for the event triggers of all native components, but it can only accept a single function pointer. If it is called multiple times, only the last function pointer provided will be used for callbacks. To release the listener, use the **unregisterNodeCustomEventReceiver** function.
16e41f4b71Sopenharmony_ci> 
17e41f4b71Sopenharmony_ci> - Custom component-related APIs ([measureNode](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#measurenode), [layoutNode](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#layoutnode), [setMeasuredSize](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#setmeasuredsize), [setLayoutPosition](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#setlayoutposition)) can only be used in the corresponding custom event callbacks ([ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodecustomeventtype)).
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci## Custom Layout Container
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ciThe following example creates a custom container that uses the maximum size of its child components, plus additional padding, as its own size, while center-aligning the child components.
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci**Figure 1** Custom container component 
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci![customContainer](figures/customContainer.png)
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci1. Follow the instructions in [Integrating with ArkTS Pages](ndk-access-the-arkts-page.md) to create a project.
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci2. Create an encapsulated object for the custom container component.
31e41f4b71Sopenharmony_ci   ```c
32e41f4b71Sopenharmony_ci   // ArkUICustomContainerNode.h
33e41f4b71Sopenharmony_ci   // Example of a custom container component
34e41f4b71Sopenharmony_ci   
35e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_ARKUICUSTOMCONTAINERNODE_H
36e41f4b71Sopenharmony_ci   #define MYAPPLICATION_ARKUICUSTOMCONTAINERNODE_H
37e41f4b71Sopenharmony_ci   
38e41f4b71Sopenharmony_ci   #include "ArkUINode.h"
39e41f4b71Sopenharmony_ci   
40e41f4b71Sopenharmony_ci   namespace NativeModule {
41e41f4b71Sopenharmony_ci   
42e41f4b71Sopenharmony_ci   class ArkUICustomContainerNode : public ArkUINode {
43e41f4b71Sopenharmony_ci   public:
44e41f4b71Sopenharmony_ci       // Create the component using the custom component type ARKUI_NODE_CUSTOM.
45e41f4b71Sopenharmony_ci       ArkUICustomContainerNode()
46e41f4b71Sopenharmony_ci           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_CUSTOM)) {
47e41f4b71Sopenharmony_ci           // Register the custom event listener.
48e41f4b71Sopenharmony_ci           nativeModule_->addNodeCustomEventReceiver(handle_, OnStaticCustomEvent);
49e41f4b71Sopenharmony_ci           // Declare the custom event and pass itself as custom data.
50e41f4b71Sopenharmony_ci           nativeModule_->registerNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE, 0, this);
51e41f4b71Sopenharmony_ci           nativeModule_->registerNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT, 0, this);
52e41f4b71Sopenharmony_ci       }
53e41f4b71Sopenharmony_ci   
54e41f4b71Sopenharmony_ci       ~ArkUICustomContainerNode() override {
55e41f4b71Sopenharmony_ci           // Deregister the custom event listener.
56e41f4b71Sopenharmony_ci           nativeModule_->removeNodeCustomEventReceiver(handle_, OnStaticCustomEvent);
57e41f4b71Sopenharmony_ci           // Undeclare the custom event.
58e41f4b71Sopenharmony_ci           nativeModule_->unregisterNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE);
59e41f4b71Sopenharmony_ci           nativeModule_->unregisterNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT);
60e41f4b71Sopenharmony_ci       }
61e41f4b71Sopenharmony_ci   
62e41f4b71Sopenharmony_ci       void SetPadding(int32_t padding) {
63e41f4b71Sopenharmony_ci           padding_ = padding;
64e41f4b71Sopenharmony_ci           // To update a custom property event, you need to proactively call the API for marking the dirty region.
65e41f4b71Sopenharmony_ci           nativeModule_->markDirty(handle_, NODE_NEED_MEASURE);
66e41f4b71Sopenharmony_ci       }
67e41f4b71Sopenharmony_ci   
68e41f4b71Sopenharmony_ci   private:
69e41f4b71Sopenharmony_ci       static void OnStaticCustomEvent(ArkUI_NodeCustomEvent *event) {
70e41f4b71Sopenharmony_ci           // Obtain the component instance object and call the related instance method.
71e41f4b71Sopenharmony_ci           auto customNode = reinterpret_cast<ArkUICustomContainerNode *>(OH_ArkUI_NodeCustomEvent_GetUserData(event));
72e41f4b71Sopenharmony_ci           auto type = OH_ArkUI_NodeCustomEvent_GetEventType(event);
73e41f4b71Sopenharmony_ci           switch (type) {
74e41f4b71Sopenharmony_ci           case ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE:
75e41f4b71Sopenharmony_ci               customNode->OnMeasure(event);
76e41f4b71Sopenharmony_ci               break;
77e41f4b71Sopenharmony_ci           case ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT:
78e41f4b71Sopenharmony_ci               customNode->OnLayout(event);
79e41f4b71Sopenharmony_ci               break;
80e41f4b71Sopenharmony_ci           default:
81e41f4b71Sopenharmony_ci               break;
82e41f4b71Sopenharmony_ci           }
83e41f4b71Sopenharmony_ci       }
84e41f4b71Sopenharmony_ci   
85e41f4b71Sopenharmony_ci       // Custom measurement logic.
86e41f4b71Sopenharmony_ci       void OnMeasure(ArkUI_NodeCustomEvent *event) {
87e41f4b71Sopenharmony_ci           auto layoutConstrain = OH_ArkUI_NodeCustomEvent_GetLayoutConstraintInMeasure(event);
88e41f4b71Sopenharmony_ci           // Create child node layout constraints, reusing the percentage reference values in the parent component layout.
89e41f4b71Sopenharmony_ci           auto childLayoutConstrain = OH_ArkUI_LayoutConstraint_Copy(layoutConstrain);
90e41f4b71Sopenharmony_ci           OH_ArkUI_LayoutConstraint_SetMaxHeight(childLayoutConstrain, 1000);
91e41f4b71Sopenharmony_ci           OH_ArkUI_LayoutConstraint_SetMaxWidth(childLayoutConstrain, 1000);
92e41f4b71Sopenharmony_ci           OH_ArkUI_LayoutConstraint_SetMinHeight(childLayoutConstrain, 0);
93e41f4b71Sopenharmony_ci           OH_ArkUI_LayoutConstraint_SetMinWidth(childLayoutConstrain, 0);
94e41f4b71Sopenharmony_ci   
95e41f4b71Sopenharmony_ci           // Measure the child nodes to get the maximum values.
96e41f4b71Sopenharmony_ci           auto totalSize = nativeModule_->getTotalChildCount(handle_);
97e41f4b71Sopenharmony_ci           int32_t maxWidth = 0;
98e41f4b71Sopenharmony_ci           int32_t maxHeight = 0;
99e41f4b71Sopenharmony_ci           for (uint32_t i = 0; i < totalSize; i++) {
100e41f4b71Sopenharmony_ci               auto child = nativeModule_->getChildAt(handle_, i);
101e41f4b71Sopenharmony_ci               // Call the measurement API to measure the native component.
102e41f4b71Sopenharmony_ci               nativeModule_->measureNode(child, childLayoutConstrain);
103e41f4b71Sopenharmony_ci               auto size = nativeModule_->getMeasuredSize(child);
104e41f4b71Sopenharmony_ci               if (size.width > maxWidth) {
105e41f4b71Sopenharmony_ci                   maxWidth = size.width;
106e41f4b71Sopenharmony_ci               }
107e41f4b71Sopenharmony_ci               if (size.height > maxHeight) {
108e41f4b71Sopenharmony_ci                   maxHeight = size.height;
109e41f4b71Sopenharmony_ci               }
110e41f4b71Sopenharmony_ci           }
111e41f4b71Sopenharmony_ci           // Custom measurement is the sum of all child node sizes plus a fixed margin.
112e41f4b71Sopenharmony_ci           nativeModule_->setMeasuredSize(handle_, maxWidth + 2 * padding_, maxHeight + 2 * padding_);
113e41f4b71Sopenharmony_ci       }
114e41f4b71Sopenharmony_ci   
115e41f4b71Sopenharmony_ci       void OnLayout(ArkUI_NodeCustomEvent *event) {
116e41f4b71Sopenharmony_ci           // Obtain the desired position of the parent component and set it.
117e41f4b71Sopenharmony_ci           auto position = OH_ArkUI_NodeCustomEvent_GetPositionInLayout(event);
118e41f4b71Sopenharmony_ci           nativeModule_->setLayoutPosition(handle_, position.x, position.y);
119e41f4b71Sopenharmony_ci   
120e41f4b71Sopenharmony_ci           // Set child components to be center-aligned.
121e41f4b71Sopenharmony_ci           auto totalSize = nativeModule_->getTotalChildCount(handle_);
122e41f4b71Sopenharmony_ci           auto selfSize = nativeModule_->getMeasuredSize(handle_);
123e41f4b71Sopenharmony_ci           for (uint32_t i = 0; i < totalSize; i++) {
124e41f4b71Sopenharmony_ci               auto child = nativeModule_->getChildAt(handle_, i);
125e41f4b71Sopenharmony_ci               // Obtain the child component size.
126e41f4b71Sopenharmony_ci               auto childSize = nativeModule_->getMeasuredSize(child);
127e41f4b71Sopenharmony_ci               // Lay out the child components.
128e41f4b71Sopenharmony_ci               nativeModule_->layoutNode(child, (selfSize.width - childSize.width) / 2,
129e41f4b71Sopenharmony_ci                                         (selfSize.height - childSize.height) / 2);
130e41f4b71Sopenharmony_ci           }
131e41f4b71Sopenharmony_ci       }
132e41f4b71Sopenharmony_ci   
133e41f4b71Sopenharmony_ci       int32_t padding_ = 100;
134e41f4b71Sopenharmony_ci   };
135e41f4b71Sopenharmony_ci   
136e41f4b71Sopenharmony_ci   } // namespace NativeModule
137e41f4b71Sopenharmony_ci   
138e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_ARKUICUSTOMCONTAINERNODE_H
139e41f4b71Sopenharmony_ci   ```
140e41f4b71Sopenharmony_ci
141e41f4b71Sopenharmony_ci3. Use the custom container to create a sample UI with text, and continue with the [timer module simple implementation](ndk-loading-long-list.md).
142e41f4b71Sopenharmony_ci   ```c
143e41f4b71Sopenharmony_ci   // Custom NDK API entry point.
144e41f4b71Sopenharmony_ci   
145e41f4b71Sopenharmony_ci   #include "NativeEntry.h"
146e41f4b71Sopenharmony_ci   
147e41f4b71Sopenharmony_ci   #include "ArkUICustomContainerNode.h"
148e41f4b71Sopenharmony_ci   #include "ArkUITextNode.h"
149e41f4b71Sopenharmony_ci   
150e41f4b71Sopenharmony_ci   #include <arkui/native_node_napi.h>
151e41f4b71Sopenharmony_ci   #include <arkui/native_type.h>
152e41f4b71Sopenharmony_ci   #include <js_native_api.h>
153e41f4b71Sopenharmony_ci   
154e41f4b71Sopenharmony_ci   namespace NativeModule {
155e41f4b71Sopenharmony_ci   
156e41f4b71Sopenharmony_ci   napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
157e41f4b71Sopenharmony_ci       size_t argc = 1;
158e41f4b71Sopenharmony_ci       napi_value args[1] = {nullptr};
159e41f4b71Sopenharmony_ci   
160e41f4b71Sopenharmony_ci       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
161e41f4b71Sopenharmony_ci   
162e41f4b71Sopenharmony_ci       // Obtain NodeContent.
163e41f4b71Sopenharmony_ci       ArkUI_NodeContentHandle contentHandle;
164e41f4b71Sopenharmony_ci       OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
165e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->SetContentHandle(contentHandle);
166e41f4b71Sopenharmony_ci   
167e41f4b71Sopenharmony_ci       // Create a custom container and text component.
168e41f4b71Sopenharmony_ci       auto node = std::make_shared<ArkUICustomContainerNode>();
169e41f4b71Sopenharmony_ci       node->SetBackgroundColor(0xFFE0FFFF);
170e41f4b71Sopenharmony_ci       auto textNode = std::make_shared<ArkUITextNode>();
171e41f4b71Sopenharmony_ci       textNode->SetTextContent("CustomContainer Example");
172e41f4b71Sopenharmony_ci       textNode->SetFontSize(16);
173e41f4b71Sopenharmony_ci       textNode->SetBackgroundColor(0xFFfffacd);
174e41f4b71Sopenharmony_ci       textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
175e41f4b71Sopenharmony_ci       node->AddChild(textNode);
176e41f4b71Sopenharmony_ci       CreateNativeTimer(env, textNode.get(), 1, [](void *userData, int32_t count) {
177e41f4b71Sopenharmony_ci           auto textNode = reinterpret_cast<ArkUITextNode *>(userData);
178e41f4b71Sopenharmony_ci           textNode->SetCircleColor(0xFF00FF7F);
179e41f4b71Sopenharmony_ci       });
180e41f4b71Sopenharmony_ci   
181e41f4b71Sopenharmony_ci       // Keep the native side object in the management class to maintain its lifecycle.
182e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->SetRootNode(node);
183e41f4b71Sopenharmony_ci       g_env = env;
184e41f4b71Sopenharmony_ci       return nullptr;
185e41f4b71Sopenharmony_ci   }
186e41f4b71Sopenharmony_ci   
187e41f4b71Sopenharmony_ci   napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
188e41f4b71Sopenharmony_ci       // Release the native side object from the management class.
189e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->DisposeRootNode();
190e41f4b71Sopenharmony_ci       return nullptr;
191e41f4b71Sopenharmony_ci   }
192e41f4b71Sopenharmony_ci   
193e41f4b71Sopenharmony_ci   } // namespace NativeModule
194e41f4b71Sopenharmony_ci   ```
195e41f4b71Sopenharmony_ci
196e41f4b71Sopenharmony_ci
197e41f4b71Sopenharmony_ci## Custom Drawing Component
198e41f4b71Sopenharmony_ci
199e41f4b71Sopenharmony_ciThe following example creates a custom drawing component that can draw a custom rectangle and uses the aforementioned custom container for layout arrangement.
200e41f4b71Sopenharmony_ci
201e41f4b71Sopenharmony_ci**Figure 2** Custom drawing component
202e41f4b71Sopenharmony_ci 
203e41f4b71Sopenharmony_ci![customNode](figures/customNode.png)
204e41f4b71Sopenharmony_ci
205e41f4b71Sopenharmony_ci1. Prepare a project as instructed in [Custom Layout Container](#custom-layout-container).
206e41f4b71Sopenharmony_ci
207e41f4b71Sopenharmony_ci2. Create an encapsulated object for the custom drawing component.
208e41f4b71Sopenharmony_ci   ```c
209e41f4b71Sopenharmony_ci   // ArkUICustomNode.h
210e41f4b71Sopenharmony_ci   // Example of a custom drawing component
211e41f4b71Sopenharmony_ci   
212e41f4b71Sopenharmony_ci   #ifndef MYAPPLICATION_ARKUICUSTOMNODE_H
213e41f4b71Sopenharmony_ci   #define MYAPPLICATION_ARKUICUSTOMNODE_H
214e41f4b71Sopenharmony_ci   
215e41f4b71Sopenharmony_ci   #include <native_drawing/drawing_brush.h>
216e41f4b71Sopenharmony_ci   #include <native_drawing/drawing_canvas.h>
217e41f4b71Sopenharmony_ci   #include <native_drawing/drawing_path.h>
218e41f4b71Sopenharmony_ci   
219e41f4b71Sopenharmony_ci   #include "ArkUINode.h"
220e41f4b71Sopenharmony_ci   
221e41f4b71Sopenharmony_ci   namespace NativeModule {
222e41f4b71Sopenharmony_ci   
223e41f4b71Sopenharmony_ci   class ArkUICustomNode : public ArkUINode {
224e41f4b71Sopenharmony_ci   public:
225e41f4b71Sopenharmony_ci       // Create the component using the custom component type ARKUI_NODE_CUSTOM.
226e41f4b71Sopenharmony_ci       ArkUICustomNode()
227e41f4b71Sopenharmony_ci           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_CUSTOM)) {
228e41f4b71Sopenharmony_ci           // Register the custom event listener.
229e41f4b71Sopenharmony_ci           nativeModule_->addNodeCustomEventReceiver(handle_, OnStaticCustomEvent);
230e41f4b71Sopenharmony_ci           // Declare the custom event and pass itself as custom data.
231e41f4b71Sopenharmony_ci           nativeModule_->registerNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW, 0, this);
232e41f4b71Sopenharmony_ci       }
233e41f4b71Sopenharmony_ci   
234e41f4b71Sopenharmony_ci       ~ArkUICustomNode() override {
235e41f4b71Sopenharmony_ci           // Deregister the custom event listener.
236e41f4b71Sopenharmony_ci           nativeModule_->removeNodeCustomEventReceiver(handle_, OnStaticCustomEvent);
237e41f4b71Sopenharmony_ci           // Undeclare the custom event.
238e41f4b71Sopenharmony_ci           nativeModule_->unregisterNodeCustomEvent(handle_, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW);
239e41f4b71Sopenharmony_ci       }
240e41f4b71Sopenharmony_ci   
241e41f4b71Sopenharmony_ci       void SetRectColor(uint32_t color) {
242e41f4b71Sopenharmony_ci           color_ = color;
243e41f4b71Sopenharmony_ci           // Custom drawing property changes require proactive notification to the framework.
244e41f4b71Sopenharmony_ci           nativeModule_->markDirty(handle_, NODE_NEED_RENDER);
245e41f4b71Sopenharmony_ci       }
246e41f4b71Sopenharmony_ci   
247e41f4b71Sopenharmony_ci   private:
248e41f4b71Sopenharmony_ci       static void OnStaticCustomEvent(ArkUI_NodeCustomEvent *event) {
249e41f4b71Sopenharmony_ci           // Obtain the component instance object and call the related instance method.
250e41f4b71Sopenharmony_ci           auto customNode = reinterpret_cast<ArkUICustomNode *>(OH_ArkUI_NodeCustomEvent_GetUserData(event));
251e41f4b71Sopenharmony_ci           auto type = OH_ArkUI_NodeCustomEvent_GetEventType(event);
252e41f4b71Sopenharmony_ci           switch (type) {
253e41f4b71Sopenharmony_ci           case ARKUI_NODE_CUSTOM_EVENT_ON_DRAW:
254e41f4b71Sopenharmony_ci               customNode->OnDraw(event);
255e41f4b71Sopenharmony_ci               break;
256e41f4b71Sopenharmony_ci           default:
257e41f4b71Sopenharmony_ci               break;
258e41f4b71Sopenharmony_ci           }
259e41f4b71Sopenharmony_ci       }
260e41f4b71Sopenharmony_ci   
261e41f4b71Sopenharmony_ci       // Custom drawing logic
262e41f4b71Sopenharmony_ci       void OnDraw(ArkUI_NodeCustomEvent *event) {
263e41f4b71Sopenharmony_ci           auto drawContext = OH_ArkUI_NodeCustomEvent_GetDrawContextInDraw(event);
264e41f4b71Sopenharmony_ci           // Obtain the graphics drawing object.
265e41f4b71Sopenharmony_ci           auto drawCanvas = reinterpret_cast<OH_Drawing_Canvas *>(OH_ArkUI_DrawContext_GetCanvas(drawContext));
266e41f4b71Sopenharmony_ci           // Obtain the component size.
267e41f4b71Sopenharmony_ci           auto size = OH_ArkUI_DrawContext_GetSize(drawContext);
268e41f4b71Sopenharmony_ci           // Draw custom content.
269e41f4b71Sopenharmony_ci           auto path = OH_Drawing_PathCreate();
270e41f4b71Sopenharmony_ci           OH_Drawing_PathMoveTo(path, size.width / 4, size.height / 4);
271e41f4b71Sopenharmony_ci           OH_Drawing_PathLineTo(path, size.width * 3 / 4, size.height / 4);
272e41f4b71Sopenharmony_ci           OH_Drawing_PathLineTo(path, size.width * 3 / 4, size.height * 3 / 4);
273e41f4b71Sopenharmony_ci           OH_Drawing_PathLineTo(path, size.width / 4, size.height * 3 / 4);
274e41f4b71Sopenharmony_ci           OH_Drawing_PathLineTo(path, size.width / 4, size.height / 4);
275e41f4b71Sopenharmony_ci           OH_Drawing_PathClose(path);
276e41f4b71Sopenharmony_ci           auto brush = OH_Drawing_BrushCreate();
277e41f4b71Sopenharmony_ci           OH_Drawing_BrushSetColor(brush, color_);
278e41f4b71Sopenharmony_ci           OH_Drawing_CanvasAttachBrush(drawCanvas, brush);
279e41f4b71Sopenharmony_ci           OH_Drawing_CanvasDrawPath(drawCanvas, path);
280e41f4b71Sopenharmony_ci           // Release resources.
281e41f4b71Sopenharmony_ci           OH_Drawing_BrushDestroy(brush);
282e41f4b71Sopenharmony_ci           OH_Drawing_PathDestroy(path);
283e41f4b71Sopenharmony_ci       }
284e41f4b71Sopenharmony_ci   
285e41f4b71Sopenharmony_ci       uint32_t color_ = 0xFFFFE4B5;
286e41f4b71Sopenharmony_ci   };
287e41f4b71Sopenharmony_ci   
288e41f4b71Sopenharmony_ci   } // namespace NativeModule
289e41f4b71Sopenharmony_ci   
290e41f4b71Sopenharmony_ci   #endif // MYAPPLICATION_ARKUICUSTOMNODE_H
291e41f4b71Sopenharmony_ci   ```
292e41f4b71Sopenharmony_ci
293e41f4b71Sopenharmony_ci3. Create a sample UI using the custom drawing component and the custom container, and continue with the [timer module simple implementation](ndk-loading-long-list.md).
294e41f4b71Sopenharmony_ci   ```c
295e41f4b71Sopenharmony_ci   // Custom NDK API entry point.
296e41f4b71Sopenharmony_ci   
297e41f4b71Sopenharmony_ci   #include "NativeEntry.h"
298e41f4b71Sopenharmony_ci   
299e41f4b71Sopenharmony_ci   #include "ArkUICustomContainerNode.h"
300e41f4b71Sopenharmony_ci   #include "ArkUICustomNode.h"
301e41f4b71Sopenharmony_ci   
302e41f4b71Sopenharmony_ci   #include <arkui/native_node_napi.h>
303e41f4b71Sopenharmony_ci   #include <arkui/native_type.h>
304e41f4b71Sopenharmony_ci   #include <js_native_api.h>
305e41f4b71Sopenharmony_ci   
306e41f4b71Sopenharmony_ci   namespace NativeModule {
307e41f4b71Sopenharmony_ci   
308e41f4b71Sopenharmony_ci   napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
309e41f4b71Sopenharmony_ci       size_t argc = 1;
310e41f4b71Sopenharmony_ci       napi_value args[1] = {nullptr};
311e41f4b71Sopenharmony_ci   
312e41f4b71Sopenharmony_ci       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
313e41f4b71Sopenharmony_ci   
314e41f4b71Sopenharmony_ci       // Obtain NodeContent.
315e41f4b71Sopenharmony_ci       ArkUI_NodeContentHandle contentHandle;
316e41f4b71Sopenharmony_ci       OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
317e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->SetContentHandle(contentHandle);
318e41f4b71Sopenharmony_ci   
319e41f4b71Sopenharmony_ci       // Create a custom container and a custom drawing component.
320e41f4b71Sopenharmony_ci       auto node = std::make_shared<ArkUICustomContainerNode>();
321e41f4b71Sopenharmony_ci       node->SetBackgroundColor(0xFFE0FFFF);
322e41f4b71Sopenharmony_ci       auto customNode = std::make_shared<ArkUICustomNode>();
323e41f4b71Sopenharmony_ci       customNode->SetBackgroundColor(0xFFD3D3D3);
324e41f4b71Sopenharmony_ci       customNode->SetWidth(150);
325e41f4b71Sopenharmony_ci       customNode->SetHeight(150);
326e41f4b71Sopenharmony_ci       node->AddChild(customNode);
327e41f4b71Sopenharmony_ci       CreateNativeTimer(env, customNode.get(), 1, [](void *userData, int32_t count) {
328e41f4b71Sopenharmony_ci           auto customNode = reinterpret_cast<ArkUICustomNode *>(userData);
329e41f4b71Sopenharmony_ci           customNode->SetRectColor(0xFF00FF7F);
330e41f4b71Sopenharmony_ci       });
331e41f4b71Sopenharmony_ci   
332e41f4b71Sopenharmony_ci       // Keep the native side object in the management class to maintain its lifecycle.
333e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->SetRootNode(node);
334e41f4b71Sopenharmony_ci       g_env = env;
335e41f4b71Sopenharmony_ci       return nullptr;
336e41f4b71Sopenharmony_ci   }
337e41f4b71Sopenharmony_ci   
338e41f4b71Sopenharmony_ci   napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
339e41f4b71Sopenharmony_ci       // Release the native side object from the management class.
340e41f4b71Sopenharmony_ci       NativeEntry::GetInstance()->DisposeRootNode();
341e41f4b71Sopenharmony_ci       return nullptr;
342e41f4b71Sopenharmony_ci   }
343e41f4b71Sopenharmony_ci   
344e41f4b71Sopenharmony_ci   } // namespace NativeModule
345e41f4b71Sopenharmony_ci   
346e41f4b71Sopenharmony_ci   ```
347