1# 监听组件事件 2 3 4NDK接口针对UI组件的事件,提供了监听函数的方式。首先,可使用[addNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addnodeeventreceiver)函数添加组件事件的监听器,该监听器会监听该组件上发生的所有事件,例如:点击事件、焦点事件。然后,可使用[registerNodeEvent](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodeevent)函数声明组件的哪些事件需要监听,NDK接口支持的事件范围通过[ArkUI_NodeEventType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeeventtype)枚举值定义。 5 6 7> **说明:** 8> - 事件注册需要声明addNodeEventReceiver监听器注册和registerNodeEvent事件类型,监听器只能监听已声明的事件。 9> 10> - 需要关注事件的反注册逻辑,如在组件销毁前调用[removeNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#removenodeeventreceiver)移除事件监听器,[unregisterNodeEvent](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#unregisternodeevent)通知ArkUI框架已监听的事件不再需要监听。 11> 12> - addNodeEventReceiver可以添加多个函数指针,每个函数指针都会在对应事件触发时触发,对应的removeNodeEventReceiver需要传递对应的函数指针用于移除监听。 13> 14> - [registerNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodeeventreceiver)是全局监听函数,不同于addNodeEventReceiver,registerEventReceiver能够监听所有Native组件的事件触发,但只能传递一个函数指针,多次调用使用最后一次的函数指针进行回调,释放时使用[ungisterNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#unregisternodeeventreceiver)进行释放。 15 16 17以下示例基于[接入ArkTS页面](ndk-access-the-arkts-page.md)章节,补充相关事件监听。 18 19 201. 在ArkUINode基类对象中实现通用事件注册逻辑。 21 ```c 22 // ArkUINode.h 23 // 提供通用属性和事件的封装。 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 // 事件触发时需要通过函数获取对应的事件对象,这边通过设置节点自定义数据将封装类指针保持在组件上,方便后续事件分发。 41 nativeModule_->setUserData(handle_, this); 42 // 注册节点监听事件接受器。 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 // 处理通用事件。 93 void RegisterOnClick(const std::function<void()> &onClick) { 94 assert(handle_); 95 onClick_ = onClick; 96 // 注册点击事件。 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 // 注册触碰事件。 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 // 注册卸载事件。 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 // 注册挂载事件。 118 nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_APPEAR, 0, nullptr); 119 } 120 121 protected: 122 // 事件监听器函数指针。 123 static void NodeEventReceiver(ArkUI_NodeEvent *event) { 124 // 获取事件发生的UI组件对象。 125 auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event); 126 // 获取保持在UI组件对象中的自定义数据,返回封装类指针。 127 auto *node = reinterpret_cast<ArkUINode *>( 128 NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle)); 129 // 基于封装类实例对象处理事件。 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 // 组件特有事件交给子类处理 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. 在ArkUIListNode对象中实现列表事件注册逻辑。 196 ```c 197 // ArkUIListNode.h 198 // 列表封装类对象 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 // 注册列表相关事件。 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 // 处理List相关事件。 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. 添加相关事件。 255 ```c 256 // TextListExample.h 257 // 文本列表示例。 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 // 创建组件并挂载 272 // 1:创建List组件。 273 auto list = std::make_shared<ArkUIListNode>(); 274 list->SetPercentWidth(1); 275 list->SetPercentHeight(1); 276 // 2:创建ListItem子组件并挂载到List上。 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 // 列表项注册点击事件。 288 listItem->RegisterOnClick([i]() { OH_LOG_INFO(LOG_APP, "on %{public}d list item click", i); }); 289 list->AddChild(listItem); 290 } 291 // 3:注册List相关监听事件. 292 list->RegisterOnScrollIndex([](int32_t index) { OH_LOG_INFO(LOG_APP, "on list scroll index: %{public}d", index); }); 293 // 4: 注册挂载事件。 294 list->RegisterOnAppear([]() { OH_LOG_INFO(LOG_APP, "on list mount to tree"); }); 295 // 4: 注册卸载事件。 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