1# Listening for Component Events
2
3
4The NDK API provides a way to listen for UI component events through listener functions. First, you can use the [addNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addnodeeventreceiver) function to add an event listener for the component, which will listen for all events that occur on that component, such as click events and focus events. Then, you can use the [registerNodeEvent](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodeevent) function to declare which events of the component need to be listened for. The range of events supported by the NDK API is defined through the [ArkUI_NodeEventType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeeventtype) enumeration values.
5
6
7> **NOTE**
8> - Event registration requires the declaration of **addNodeEventReceiver** listener registration and **registerNodeEvent** event types. The listener can only listen for declared events.
9>
10> - Pay attention to the logic of event deregistration. For example, before the component is destroyed, call [removeNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#removenodeeventreceiver) to remove the event listener and [unregisterNodeEvent](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#unregisternodeevent) to notify the ArkUI framework that the listened events no longer need to be listened for.
11>
12> - **addNodeEventReceiver** can add multiple function pointers, each of which is triggered when the corresponding event occurs. To remove a listener, the corresponding **removeNodeEventReceiver** function must be called with the exact function pointer used for adding the listener.
13>
14> - [registerNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodeeventreceiver) is a global event listener function. Unlike **addNodeEventReceiver**, **registerNodeEventReceiver** 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 [ungisterNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#unregisternodeeventreceiver) function.
15
16
17The following example is based on the [Integrating with ArkTS Pages](ndk-access-the-arkts-page.md) section, supplementing related event listening.
18
19
201. Implement common event registration logic in the **ArkUINode** base class object.
21   ```c
22   // ArkUINode.h
23   // Provide encapsulation of common properties and events.
24
25   #ifndef MYAPPLICATION_ARKUINODE_H
26   #define MYAPPLICATION_ARKUINODE_H
27
28   #include "ArkUIBaseNode.h"
29   #include "NativeModule.h"
30
31   #include <arkui/native_node.h>
32   #include <arkui/native_type.h>
33
34   namespace NativeModule {
35
36   class ArkUINode : public ArkUIBaseNode {
37   public:
38       explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle) {
39           nativeModule_ = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
40           // When an event is triggered, you need to get the corresponding event object through a function. Here, by setting the node's custom data, the encapsulated class pointer is kept on the component for subsequent event distribution.
41           nativeModule_->setUserData(handle_, this);
42           // Register the node event receiver.
43           nativeModule_->addNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver);
44       }
45
46       ~ArkUINode() override {
47           if (onClick_) {
48               nativeModule_->unregisterNodeEvent(handle_, NODE_ON_CLICK);
49           }
50           if (onTouch_) {
51               nativeModule_->unregisterNodeEvent(handle_, NODE_TOUCH_EVENT);
52           }
53           if (onDisappear) {
54               nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR);
55           }
56           if (onAppear) {
57               nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_APPEAR);
58           }
59           nativeModule_->removeNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver);
60       }
61
62       void SetWidth(float width) {
63           assert(handle_);
64           ArkUI_NumberValue value[] = {{.f32 = width}};
65           ArkUI_AttributeItem item = {value, 1};
66           nativeModule_->setAttribute(handle_, NODE_WIDTH, &item);
67       }
68       void SetPercentWidth(float percent) {
69           assert(handle_);
70           ArkUI_NumberValue value[] = {{.f32 = percent}};
71           ArkUI_AttributeItem item = {value, 1};
72           nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item);
73       }
74       void SetHeight(float height) {
75           assert(handle_);
76           ArkUI_NumberValue value[] = {{.f32 = height}};
77           ArkUI_AttributeItem item = {value, 1};
78           nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item);
79       }
80       void SetPercentHeight(float percent) {
81           assert(handle_);
82           ArkUI_NumberValue value[] = {{.f32 = percent}};
83           ArkUI_AttributeItem item = {value, 1};
84           nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item);
85       }
86       void SetBackgroundColor(uint32_t color) {
87           assert(handle_);
88           ArkUI_NumberValue value[] = {{.u32 = color}};
89           ArkUI_AttributeItem item = {value, 1};
90           nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item);
91       }
92       // Process common events.
93       void RegisterOnClick(const std::function<void()> &onClick) {
94           assert(handle_);
95           onClick_ = onClick;
96           // Register the click event.
97           nativeModule_->registerNodeEvent(handle_, NODE_ON_CLICK, 0, nullptr);
98       }
99
100       void RegisterOnTouch(const std::function<void(int32_t type, float x, float y)> &onTouch) {
101           assert(handle_);
102           onTouch_ = onTouch;
103           // Register the touch event.
104           nativeModule_->registerNodeEvent(handle_, NODE_TOUCH_EVENT, 0, nullptr);
105       }
106
107       void RegisterOnDisappear(const std::function<void()> &onDisappear) {
108           assert(handle_);
109           onDisappear_ = onDisappear;
110           // Register the disappear event.
111           nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR, 0, nullptr);
112       }
113
114       void RegisterOnAppear(const std::function<void()> &onAppear) {
115           assert(handle_);
116           onAppear_ = onAppear;
117           // Register the appear event.
118           nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_APPEAR, 0, nullptr);
119       }
120
121   protected:
122       // Event listener function pointer.
123       static void NodeEventReceiver(ArkUI_NodeEvent *event) {
124           // Obtain the UI component object where the event occurs.
125           auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event);
126           // Obtain the custom data kept in the UI component object, and return the encapsulated class pointer.
127           auto *node = reinterpret_cast<ArkUINode *>(
128               NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle));
129           // Process the event based on the encapsulated class instance object.
130           node->ProcessNodeEvent(event);
131       }
132       void ProcessNodeEvent(ArkUI_NodeEvent *event) {
133           auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
134           switch (eventType) {
135           case NODE_ON_CLICK: {
136               if (onClick_) {
137                   onClick_();
138               }
139               break;
140           }
141           case NODE_TOUCH_EVENT: {
142               if (onTouch_) {
143                   auto *uiInputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
144                   float x = OH_ArkUI_PointerEvent_GetX(uiInputEvent);
145                   float y = OH_ArkUI_PointerEvent_GetY(uiInputEvent);
146                   auto type = OH_ArkUI_UIInputEvent_GetAction(uiInputEvent);
147                   onTouch_(type, x, y);
148               }
149           }
150           case NODE_EVENT_ON_DISAPPEAR: {
151               if (onDisappear_) {
152                   onDisappear_();
153               }
154               break;
155           }
156           case NODE_EVENT_ON_APPEAR: {
157               if (onAppear_) {
158                   onAppear_();
159               }
160               break;
161           }
162           default: {
163               // Component-specific events are processed by subclasses.
164               OnNodeEvent(event);
165           }
166           }
167       }
168
169       virtual void OnNodeEvent(ArkUI_NodeEvent *event) {}
170
171       void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
172           nativeModule_->addChild(handle_, child->GetHandle());
173       }
174
175       void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
176           nativeModule_->removeChild(handle_, child->GetHandle());
177       }
178
179       void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override {
180           nativeModule_->insertChildAt(handle_, child->GetHandle(), index);
181       }
182
183   private:
184       std::function<void()> onClick_;
185       std::function<void()> onDisappear_;
186       std::function<void()> onAppear_;
187       std::function<void(int32_t type, float x, float y)> onTouch_;
188   };
189   } // namespace NativeModule
190
191   #endif // MYAPPLICATION_ARKUINODE_H
192
193   ```
194
1952. Implement list event registration logic in the **ArkUIListNode** object.
196   ```c
197   // ArkUIListNode.h
198   // List encapsulation class object
199
200   #ifndef MYAPPLICATION_ARKUILISTNODE_H
201   #define MYAPPLICATION_ARKUILISTNODE_H
202
203   #include "ArkUINode.h"
204   #include <hilog/log.h>
205
206   namespace NativeModule {
207   class ArkUIListNode : public ArkUINode {
208   public:
209       ArkUIListNode()
210           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {}
211
212       ~ArkUIListNode() override { nativeModule_->unregisterNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX); }
213
214       void SetScrollBarState(bool isShow) {
215           assert(handle_);
216           ArkUI_ScrollBarDisplayMode displayMode =
217               isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF;
218           ArkUI_NumberValue value[] = {{.i32 = displayMode}};
219           ArkUI_AttributeItem item = {value, 1};
220           nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item);
221       }
222
223       // Register list-related events.
224       void RegisterOnScrollIndex(const std::function<void(int32_t index)> &onScrollIndex) {
225           assert(handle_);
226           onScrollIndex_ = onScrollIndex;
227           nativeModule_->registerNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX, 0, nullptr);
228       }
229
230   protected:
231      // Process list-related events.
232       void OnNodeEvent(ArkUI_NodeEvent *event) override {
233           auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
234           switch (eventType) {
235           case NODE_LIST_ON_SCROLL_INDEX: {
236               auto index = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event)->data[0];
237               if (onScrollIndex_) {
238                   onScrollIndex_(index.i32);
239               }
240           }
241           default: {
242           }
243           }
244       }
245
246   private:
247       std::function<void(int32_t index)> onScrollIndex_;
248   };
249   } // namespace NativeModule
250
251   #endif // MYAPPLICATION_ARKUILISTNODE_H
252   ```
253
2543. Add related events.
255   ```c
256   // TextListExample.h
257   // Text list example.
258
259   #ifndef MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
260   #define MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
261
262   #include "ArkUIBaseNode.h"
263   #include "ArkUIListItemNode.h"
264   #include "ArkUIListNode.h"
265   #include "ArkUITextNode.h"
266   #include <hilog/log.h>
267
268   namespace NativeModule {
269
270   std::shared_ptr<ArkUIBaseNode> CreateTextListExample() {
271       // Create components and mount them.
272       // 1: Create a List component.
273       auto list = std::make_shared<ArkUIListNode>();
274       list->SetPercentWidth(1);
275       list->SetPercentHeight(1);
276       // 2: Create a ListItem child component and mount it to the List component.
277       for (int32_t i = 0; i < 30; ++i) {
278           auto listItem = std::make_shared<ArkUIListItemNode>();
279           auto textNode = std::make_shared<ArkUITextNode>();
280           textNode->SetTextContent(std::to_string(i));
281           textNode->SetFontSize(16);
282           textNode->SetPercentWidth(1);
283           textNode->SetHeight(100);
284           textNode->SetBackgroundColor(0xFFfffacd);
285           textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
286           listItem->AddChild(textNode);
287           // Register the click event for the list item.
288           listItem->RegisterOnClick([i]() { OH_LOG_INFO(LOG_APP, "on %{public}d list item click", i); });
289           list->AddChild(listItem);
290       }
291       // 3: Register list-related listening events.
292       list->RegisterOnScrollIndex([](int32_t index) { OH_LOG_INFO(LOG_APP, "on list scroll index: %{public}d", index); });
293       // 4: Register the appear event.
294       list->RegisterOnAppear([]() { OH_LOG_INFO(LOG_APP, "on list mount to tree"); });
295       // 4: Register the disappear event.
296       list->RegisterOnDisappear([]() { OH_LOG_INFO(LOG_APP, "on list unmount from tree"); });
297       return list;
298   }
299   } // namespace NativeModule
300
301   #endif // MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
302
303   ```
304