• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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](../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)事件类型,监听器只能监听已声明的事件。
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](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addnodeeventreceiver)可以添加多个函数指针,每个函数指针都会在对应事件触发时触发,对应的[removeNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#removenodeeventreceiver)需要传递对应的函数指针用于移除监听。
13>
14> - [registerNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodeeventreceiver)是全局监听函数,不同于[addNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#addnodeeventreceiver),[registerNodeEventReceiver](../reference/apis-arkui/_ark_u_i___native_node_a_p_i__1.md#registernodeeventreceiver)能够监听所有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
20- 事件注册和事件解注册
21
22  通过addNodeEventReceiver对节点绑定事件处理函数,接着通过调用registerNodeEvent注册对应的事件。
23
24  > 说明:
25  >
26  > 事件监听函数的入参ArkUI_NodeEvent* event的生命周期只在函数回调周期内生效,不推荐对该指针进行缓存或者进行异步处理。
27
28  ```
29  ArkUI_NativeNodeAPI_1 *nodeAPI = nullptr;
30  OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI);
31  void NodeEventReceiver(ArkUI_NodeEvent *event) {
32    // 设置对应的事件类型触发时进行的操作,如NODE_ON_CLICK
33  };
34  auto button = nodeAPI->createNode(ARKUI_NODE_BUTTON);
35  nodeAPI->addNodeEventReceiver(button, NodeEventReceiver);
36  nodeAPI->registerNodeEvent(button, NODE_ON_CLICK, 0, nullptr);
37  ```
38  详细的事件类型请参考[ArkUI_NodeEventType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeeventtype)。
39
40  通过unregisterNodeEvent解注册对应的事件类型,再通过removeNodeEventReceiver卸载事件处理函数。
41
42  ```
43  nodeAPI->unregisterNodeEvent(button, NODE_ON_CLICK);
44  nodeAPI->removeNodeEventReceiver(button, NodeEventReceiver);
45  ```
46
47- 全局事件监听
48
49  使用registerNodeEventReceiver注册全局的事件处理函数,对事件进行统一的处理,结束后可使用ungisterNodeEventReceiver进行释放。
50
51  ```
52  nodeAPI->registerNodeEventReceiver([](ArkUI_NodeEvent *event){
53    auto *inputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
54    auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
55    case NODE_ON_CLICK: {
56        // 触发点击事件所进行的操作
57    }
58    default: {
59        break;
60    }
61  })
62  nodeAPI->unregisterNodeEventReceiver();
63  ```
64
65**完整示例:**
66
671. 在ArkUINode基类对象中实现通用事件注册逻辑。
68
69   ```c
70   // ArkUINode.h
71   // 提供通用属性和事件的封装。
72
73   #ifndef MYAPPLICATION_ARKUINODE_H
74   #define MYAPPLICATION_ARKUINODE_H
75
76   #include "ArkUIBaseNode.h"
77   #include "NativeModule.h"
78
79   #include <arkui/native_node.h>
80   #include <arkui/native_type.h>
81
82   namespace NativeModule {
83
84   class ArkUINode : public ArkUIBaseNode {
85   public:
86       explicit ArkUINode(ArkUI_NodeHandle handle) : ArkUIBaseNode(handle) {
87           nativeModule_ = NativeModuleInstance::GetInstance()->GetNativeNodeAPI();
88           // 事件触发时需要通过函数获取对应的事件对象,这边通过设置节点自定义数据将封装类指针保持在组件上,方便后续事件分发。
89           nativeModule_->setUserData(handle_, this);
90           // 注册节点监听事件接受器。
91           nativeModule_->addNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver);
92       }
93
94       ~ArkUINode() override {
95           if (onClick_) {
96               nativeModule_->unregisterNodeEvent(handle_, NODE_ON_CLICK);
97           }
98           if (onTouch_) {
99               nativeModule_->unregisterNodeEvent(handle_, NODE_TOUCH_EVENT);
100           }
101           if (onDisappear_) {
102               nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR);
103           }
104           if (onAppear_) {
105               nativeModule_->unregisterNodeEvent(handle_, NODE_EVENT_ON_APPEAR);
106           }
107           nativeModule_->removeNodeEventReceiver(handle_, ArkUINode::NodeEventReceiver);
108       }
109
110       void SetWidth(float width) {
111           assert(handle_);
112           ArkUI_NumberValue value[] = {{.f32 = width}};
113           ArkUI_AttributeItem item = {value, 1};
114           nativeModule_->setAttribute(handle_, NODE_WIDTH, &item);
115       }
116       void SetPercentWidth(float percent) {
117           assert(handle_);
118           ArkUI_NumberValue value[] = {{.f32 = percent}};
119           ArkUI_AttributeItem item = {value, 1};
120           nativeModule_->setAttribute(handle_, NODE_WIDTH_PERCENT, &item);
121       }
122       void SetHeight(float height) {
123           assert(handle_);
124           ArkUI_NumberValue value[] = {{.f32 = height}};
125           ArkUI_AttributeItem item = {value, 1};
126           nativeModule_->setAttribute(handle_, NODE_HEIGHT, &item);
127       }
128       void SetPercentHeight(float percent) {
129           assert(handle_);
130           ArkUI_NumberValue value[] = {{.f32 = percent}};
131           ArkUI_AttributeItem item = {value, 1};
132           nativeModule_->setAttribute(handle_, NODE_HEIGHT_PERCENT, &item);
133       }
134       void SetBackgroundColor(uint32_t color) {
135           assert(handle_);
136           ArkUI_NumberValue value[] = {{.u32 = color}};
137           ArkUI_AttributeItem item = {value, 1};
138           nativeModule_->setAttribute(handle_, NODE_BACKGROUND_COLOR, &item);
139       }
140       // 处理通用事件。
141       void RegisterOnClick(const std::function<void()> &onClick) {
142           assert(handle_);
143           onClick_ = onClick;
144           // 注册点击事件。
145           nativeModule_->registerNodeEvent(handle_, NODE_ON_CLICK, 0, nullptr);
146       }
147
148       void RegisterOnTouch(const std::function<void(int32_t type, float x, float y)> &onTouch) {
149           assert(handle_);
150           onTouch_ = onTouch;
151           // 注册触碰事件。
152           nativeModule_->registerNodeEvent(handle_, NODE_TOUCH_EVENT, 0, nullptr);
153       }
154
155       void RegisterOnDisappear(const std::function<void()> &onDisappear) {
156           assert(handle_);
157           onDisappear_ = onDisappear;
158           // 注册卸载事件。
159           nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_DISAPPEAR, 0, nullptr);
160       }
161
162       void RegisterOnAppear(const std::function<void()> &onAppear) {
163           assert(handle_);
164           onAppear_ = onAppear;
165           // 注册挂载事件。
166           nativeModule_->registerNodeEvent(handle_, NODE_EVENT_ON_APPEAR, 0, nullptr);
167       }
168
169   protected:
170       // 事件监听器函数指针。
171       static void NodeEventReceiver(ArkUI_NodeEvent *event) {
172           // 获取事件发生的UI组件对象。
173           auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event);
174           // 获取保持在UI组件对象中的自定义数据,返回封装类指针。
175           auto *node = reinterpret_cast<ArkUINode *>(
176               NativeModuleInstance::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle));
177           // 基于封装类实例对象处理事件。
178           node->ProcessNodeEvent(event);
179       }
180       void ProcessNodeEvent(ArkUI_NodeEvent *event) {
181           auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
182           switch (eventType) {
183           case NODE_ON_CLICK: {
184               if (onClick_) {
185                   onClick_();
186               }
187               break;
188           }
189           case NODE_TOUCH_EVENT: {
190               if (onTouch_) {
191                   auto *uiInputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
192                   float x = OH_ArkUI_PointerEvent_GetX(uiInputEvent);
193                   float y = OH_ArkUI_PointerEvent_GetY(uiInputEvent);
194                   auto type = OH_ArkUI_UIInputEvent_GetAction(uiInputEvent);
195                   onTouch_(type, x, y);
196               }
197           }
198           case NODE_EVENT_ON_DISAPPEAR: {
199               if (onDisappear_) {
200                   onDisappear_();
201               }
202               break;
203           }
204           case NODE_EVENT_ON_APPEAR: {
205               if (onAppear_) {
206                   onAppear_();
207               }
208               break;
209           }
210           default: {
211               // 组件特有事件交给子类处理
212               OnNodeEvent(event);
213           }
214           }
215       }
216
217       virtual void OnNodeEvent(ArkUI_NodeEvent *event) {}
218
219       void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
220           nativeModule_->addChild(handle_, child->GetHandle());
221       }
222
223       void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) override {
224           nativeModule_->removeChild(handle_, child->GetHandle());
225       }
226
227       void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) override {
228           nativeModule_->insertChildAt(handle_, child->GetHandle(), index);
229       }
230
231   private:
232       std::function<void()> onClick_;
233       std::function<void()> onDisappear_;
234       std::function<void()> onAppear_;
235       std::function<void(int32_t type, float x, float y)> onTouch_;
236   };
237   } // namespace NativeModule
238
239   #endif // MYAPPLICATION_ARKUINODE_H
240
241   ```
242
2432. 在ArkUIListNode对象中实现列表事件注册逻辑。
244   ```c
245   // ArkUIListNode.h
246   // 列表封装类对象
247
248   #ifndef MYAPPLICATION_ARKUILISTNODE_H
249   #define MYAPPLICATION_ARKUILISTNODE_H
250
251   #include "ArkUINode.h"
252   #include <hilog/log.h>
253
254   namespace NativeModule {
255   class ArkUIListNode : public ArkUINode {
256   public:
257       ArkUIListNode()
258           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {}
259
260       ~ArkUIListNode() override { nativeModule_->unregisterNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX); }
261
262       void SetScrollBarState(bool isShow) {
263           assert(handle_);
264           ArkUI_ScrollBarDisplayMode displayMode =
265               isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF;
266           ArkUI_NumberValue value[] = {{.i32 = displayMode}};
267           ArkUI_AttributeItem item = {value, 1};
268           nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item);
269       }
270
271       // 注册列表相关事件。
272       void RegisterOnScrollIndex(const std::function<void(int32_t index)> &onScrollIndex) {
273           assert(handle_);
274           onScrollIndex_ = onScrollIndex;
275           nativeModule_->registerNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX, 0, nullptr);
276       }
277
278   protected:
279      // 处理List相关事件。
280       void OnNodeEvent(ArkUI_NodeEvent *event) override {
281           auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
282           switch (eventType) {
283           case NODE_LIST_ON_SCROLL_INDEX: {
284               auto index = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event)->data[0];
285               if (onScrollIndex_) {
286                   onScrollIndex_(index.i32);
287               }
288           }
289           default: {
290           }
291           }
292       }
293
294   private:
295       std::function<void(int32_t index)> onScrollIndex_;
296   };
297   } // namespace NativeModule
298
299   #endif // MYAPPLICATION_ARKUILISTNODE_H
300   ```
301
3023. 添加相关事件。
303   ```c
304   // TextListExample.h
305   // 文本列表示例。
306
307   #ifndef MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
308   #define MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
309
310   #include "ArkUIBaseNode.h"
311   #include "ArkUIListItemNode.h"
312   #include "ArkUIListNode.h"
313   #include "ArkUITextNode.h"
314   #include <hilog/log.h>
315
316   namespace NativeModule {
317
318   std::shared_ptr<ArkUIBaseNode> CreateTextListExample() {
319       // 创建组件并挂载
320       // 1:创建List组件。
321       auto list = std::make_shared<ArkUIListNode>();
322       list->SetPercentWidth(1);
323       list->SetPercentHeight(1);
324       // 2:创建ListItem子组件并挂载到List上。
325       for (int32_t i = 0; i < 30; ++i) {
326           auto listItem = std::make_shared<ArkUIListItemNode>();
327           auto textNode = std::make_shared<ArkUITextNode>();
328           textNode->SetTextContent(std::to_string(i));
329           textNode->SetFontSize(16);
330           textNode->SetPercentWidth(1);
331           textNode->SetHeight(100);
332           textNode->SetBackgroundColor(0xFFfffacd);
333           textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
334           listItem->AddChild(textNode);
335           // 列表项注册点击事件。
336           listItem->RegisterOnClick([i]() { OH_LOG_INFO(LOG_APP, "on %{public}d list item click", i); });
337           list->AddChild(listItem);
338       }
339       // 3:注册List相关监听事件.
340       list->RegisterOnScrollIndex([](int32_t index) { OH_LOG_INFO(LOG_APP, "on list scroll index: %{public}d", index); });
341       // 4: 注册挂载事件。
342       list->RegisterOnAppear([]() { OH_LOG_INFO(LOG_APP, "on list mount to tree"); });
343       // 4: 注册卸载事件。
344       list->RegisterOnDisappear([]() { OH_LOG_INFO(LOG_APP, "on list unmount from tree"); });
345       return list;
346   }
347   } // namespace NativeModule
348
349   #endif // MYAPPLICATION_NORMALTEXTLISTEXAMPLE_H
350
351   ```
352