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