• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用列表
2
3
4ArkUI开发框架在NDK接口提供了列表组件,使用列表可以轻松高效地显示结构化、可滚动的信息。列表组件支持控制滚动位置、支持分组显示内容、持使用NodeAdapter实现懒加载以提升列表创建性能。
5
6## 创建列表
7
8参考[接入ArkTS页面章节](../ui/ndk-access-the-arkts-page.md)实现列表创建。
9
10## 监听滚动事件
11
12参考监听组件事件章节实现列表滚动事件监听。
13
14## 使用懒加载
15
16### NodeAdapter介绍
17
18NDK提供了[NodeAdapter](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadapterhandle)对象替代ArkTS侧的LazyForEach功能,用于按需生成子组件,NodeAdapter支持在List/ListItemGroup、Gird、WaterFlow、Swiper组件中使用。
19
20- 设置了NodeAdapter属性的节点,不再支持addChild等直接添加子组件的接口。子组件完全由NodeAdapter管理,使用属性方法设置NodeAdapter时,会判断父组件是否已经存在子节点,如果父组件已经存在子节点,则设置NodeAdapter操作失败,返回错误码。
21
22- NodeApdater通过相关事件通知开发者按需生成组件,类似组件事件机制,开发者使用NodeAdapter时要注册[事件监听器](../reference/apis-arkui/_ark_u_i___native_module.md#oh_arkui_nodeadapter_registereventreceiver),在监听器事件中处理逻辑,相关事件通过[ArkUI_NodeAdapterEventType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadaptereventtype)定义。另外NodeAdapter不会主动释放不在屏幕内显示的组件对象,开发者需要在[NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadaptereventtype)事件中进行组件对象的释放,或者进行缓存复用。下图展示了典型列表滑动场景下的事件触发机制:
23  ![zh-cn_image_0000001949769409](figures/zh-cn_image_0000001949769409.png)
24
25
26### 实现懒加载适配器
27
28使用ArkUListItemAdapter类来管理懒加载适配器,在类的构造中创建NodeAdapter对象,并给NodeAdapter对象设置事件监听器,在类的析构函数中,销毁NodeAdapter对象。
29
30   ```c++
31   // ArkUIListItemAdapter
32   // 用于文本列表懒加载功能代码。
33
34   #ifndef MYAPPLICATION_ARKUILISTITEMADAPTER_H
35   #define MYAPPLICATION_ARKUILISTITEMADAPTER_H
36
37   #include <arkui/native_node.h>
38   #include <stack>
39   #include <string>
40   #include <unordered_set>
41
42   #include "ArkUIListItemNode.h"
43   #include "ArkUITextNode.h"
44   #include "nativeModule.h"
45
46   namespace NativeModule {
47
48   class ArkUIListItemAdapter {
49   public:
50       ArkUIListItemAdapter()
51           : module_(NativeModuleInstance::GetInstance()->GetNativeNodeAPI()), handle_(OH_ArkUI_NodeAdapter_Create()) { // 使用NodeAdapter创建函数。
52           // 初始化懒加载数据。
53           for (int32_t i = 0; i < 1000; i++) {
54               data_.emplace_back(std::to_string(i));
55           }
56           // 设置懒加载数据。
57           OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
58           // 设置懒加载回调事件。
59           OH_ArkUI_NodeAdapter_RegisterEventReceiver(handle_, this, OnStaticAdapterEvent);
60       }
61
62       ~ArkUIListItemAdapter() {
63           // 释放创建的组件。
64           while (!cachedItems_.empty()) {
65               cachedItems_.pop();
66           }
67           items_.clear();
68           // 释放Adapter相关资源。
69           OH_ArkUI_NodeAdapter_UnregisterEventReceiver(handle_);
70           OH_ArkUI_NodeAdapter_Dispose(handle_);
71       }
72
73       ArkUI_NodeAdapterHandle GetHandle() const { return handle_; }
74
75       void RemoveItem(int32_t index) {
76           // 删除第index个数据。
77           data_.erase(data_.begin() + index);
78           // 如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件删除元素,
79           // 根据是否有新增元素回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。
80           OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1);
81           // 更新新的数量。
82           OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
83       }
84
85       void InsertItem(int32_t index, const std::string &value) {
86           data_.insert(data_.begin() + index, value);
87           // 如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件,
88           // 根据是否有删除元素回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER事件。
89           OH_ArkUI_NodeAdapter_InsertItem(handle_, index, 1);
90           // 更新新的数量。
91           OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
92       }
93
94       void MoveItem(int32_t oldIndex, int32_t newIndex) {
95           auto temp = data_[oldIndex];
96           data_.insert(data_.begin() + newIndex, temp);
97           data_.erase(data_.begin() + oldIndex);
98           // 移到位置如果未发生可视区域内元素的可见性变化,则不回调事件,反之根据新增和删除场景回调对应的事件。
99           OH_ArkUI_NodeAdapter_MoveItem(handle_, oldIndex, newIndex);
100       }
101
102       void ReloadItem(int32_t index, const std::string &value) {
103           data_[index] = value;
104           // 如果index位于可视区域内,先回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER删除老元素,
105           // 再回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。
106           OH_ArkUI_NodeAdapter_ReloadItem(handle_, index, 1);
107       }
108
109       void ReloadAllItem() {
110           std::reverse(data_.begin(), data_.end());
111           // 全部重新加载场景下,会回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID接口获取新的组件ID,
112           // 根据新的组件ID进行对比,ID不发生变化的进行复用,
113           // 针对新增ID的元素,调用NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件创建新的组件,
114           // 然后判断老数据中遗留的未使用ID,调用NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER删除老元素。
115           OH_ArkUI_NodeAdapter_ReloadAllItems(handle_);
116       }
117
118   private:
119       static void OnStaticAdapterEvent(ArkUI_NodeAdapterEvent *event) {
120           // 获取实例对象,回调实例事件。
121           auto itemAdapter = reinterpret_cast<ArkUIListItemAdapter *>(OH_ArkUI_NodeAdapterEvent_GetUserData(event));
122           itemAdapter->OnAdapterEvent(event);
123       }
124
125       void OnAdapterEvent(ArkUI_NodeAdapterEvent *event) {
126           auto type = OH_ArkUI_NodeAdapterEvent_GetType(event);
127           switch (type) {
128           case NODE_ADAPTER_EVENT_ON_GET_NODE_ID:
129               OnNewItemIdCreated(event);
130               break;
131           case NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER:
132               OnNewItemAttached(event);
133               break;
134           case NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER:
135               OnItemDetached(event);
136               break;
137           default:
138               break;
139           }
140       }
141
142       // 分配ID给需要显示的Item,用于ReloadAllItems场景的元素diff。
143       void OnNewItemIdCreated(ArkUI_NodeAdapterEvent *event) {
144           auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event);
145           static std::hash<std::string> hashId = std::hash<std::string>();
146           auto id = hashId(data_[index]);
147           OH_ArkUI_NodeAdapterEvent_SetNodeId(event, id);
148       }
149
150       // 需要新的Item显示在可见区域。
151       void OnNewItemAttached(ArkUI_NodeAdapterEvent *event) {
152           auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event);
153           ArkUI_NodeHandle handle = nullptr;
154           if (!cachedItems_.empty()) {
155               // 使用并更新回收复用的缓存。
156               auto recycledItem = cachedItems_.top();
157               auto textItem = std::dynamic_pointer_cast<ArkUITextNode>(recycledItem->GetChildren().back());
158               textItem->SetTextContent(data_[index]);
159               handle = recycledItem->GetHandle();
160               // 释放缓存池的引用。
161               cachedItems_.pop();
162           } else {
163               // 创建新的元素。
164               auto listItem = std::make_shared<ArkUIListItemNode>();
165               auto textNode = std::make_shared<ArkUITextNode>();
166               textNode->SetTextContent(data_[index]);
167               textNode->SetFontSize(16);
168               textNode->SetPercentWidth(1);
169               textNode->SetHeight(100);
170               textNode->SetBackgroundColor(0xFFfffacd);
171               textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
172               listItem->AddChild(textNode);
173               listItem->RegisterOnClick([index]() { OH_LOG_INFO(LOG_APP, "on %{public}d list item click", index); });
174               handle = listItem->GetHandle();
175               // 保持文本列表项的引用。
176               items_.emplace(handle, listItem);
177           }
178           // 设置需要展示的元素。
179           OH_ArkUI_NodeAdapterEvent_SetItem(event, handle);
180       }
181
182       // Item从可见区域移除。
183       void OnItemDetached(ArkUI_NodeAdapterEvent *event) {
184           auto item = OH_ArkUI_NodeAdapterEvent_GetRemovedNode(event);
185           // 放置到缓存池中进行回收复用。
186           cachedItems_.emplace(items_[item]);
187       }
188
189
190       std::vector<std::string> data_;
191       ArkUI_NativeNodeAPI_1 *module_ = nullptr;
192       ArkUI_NodeAdapterHandle handle_ = nullptr;
193
194       // 管理NodeAdapter生成的元素。
195       std::unordered_map<ArkUI_NodeHandle, std::shared_ptr<ArkUIListItemNode>> items_;
196
197       // 管理回收复用组件池。
198       std::stack<std::shared_ptr<ArkUIListItemNode>> cachedItems_;
199   };
200
201   } // namespace NativeModule
202
203   #endif // MYAPPLICATION_ARKUILISTITEMADAPTER_H
204   ```
205
206### 在列表中应用懒加载适配器
207
2081. 在ArkUIListNode中添加SetLazyAdapter函数,给列表节设置NODE_LIST_NODE_ADAPTER属性,并将NodeAdapter作为属性入参传入。
209   ```c++
210   // ArkUIListNode.h
211   // 列表封装对象。
212
213   #ifndef MYAPPLICATION_ARKUILISTNODE_H
214   #define MYAPPLICATION_ARKUILISTNODE_H
215
216   #include "ArkUIListItemAdapter.h"
217   #include "ArkUINode.h"
218   #include <hilog/log.h>
219
220   namespace NativeModule {
221   class ArkUIListNode : public ArkUINode {
222   public:
223       ArkUIListNode()
224           : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST)) {}
225
226       ~ArkUIListNode() override {
227           nativeModule_->unregisterNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX);
228           if (adapter_) {
229               // 析构的时候卸载adapter下的UI组件。
230               nativeModule_->resetAttribute(handle_, NODE_LIST_NODE_ADAPTER);
231               adapter_.reset();
232           }
233       }
234
235       void SetScrollBarState(bool isShow) {
236           assert(handle_);
237           ArkUI_ScrollBarDisplayMode displayMode =
238               isShow ? ARKUI_SCROLL_BAR_DISPLAY_MODE_ON : ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF;
239           ArkUI_NumberValue value[] = {{.i32 = displayMode}};
240           ArkUI_AttributeItem item = {value, 1};
241           nativeModule_->setAttribute(handle_, NODE_SCROLL_BAR_DISPLAY_MODE, &item);
242       }
243
244       void RegisterOnScrollIndex(const std::function<void(int32_t index)> &onScrollIndex) {
245           assert(handle_);
246           onScrollIndex_ = onScrollIndex;
247           nativeModule_->registerNodeEvent(handle_, NODE_LIST_ON_SCROLL_INDEX, 0, nullptr);
248       }
249       // 引入懒加载模块。
250       void SetLazyAdapter(const std::shared_ptr<ArkUIListItemAdapter> &adapter) {
251           assert(handle_);
252           ArkUI_AttributeItem item{nullptr, 0, nullptr, adapter->GetHandle()};
253           nativeModule_->setAttribute(handle_, NODE_LIST_NODE_ADAPTER, &item);
254           adapter_ = adapter;
255       }
256
257   protected:
258       void OnNodeEvent(ArkUI_NodeEvent *event) override {
259           auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
260           switch (eventType) {
261           case NODE_LIST_ON_SCROLL_INDEX: {
262               auto index = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event)->data[0];
263               if (onScrollIndex_) {
264                   onScrollIndex_(index.i32);
265               }
266           }
267           default: {
268           }
269           }
270       }
271
272   private:
273       std::function<void(int32_t index)> onScrollIndex_;
274
275       std::shared_ptr<ArkUIListItemAdapter> adapter_;
276   };
277   } // namespace NativeModule
278
279   #endif // MYAPPLICATION_ARKUILISTNODE_H
280   ```
281
2822. 创建List使用懒加载的示例代码,调用List节点的SetLazyAdapter接口设置懒加载适配器。
283   ```c++
284   // LazyTextListExample
285   // 懒加载列表示例代码。
286
287   #ifndef MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
288   #define MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
289
290   #include "ArkUIBaseNode.h"
291   #include "ArkUIListNode.h"
292
293
294   namespace NativeModule {
295
296   std::shared_ptr<ArkUIBaseNode> CreateLazyTextListExample(napi_env env) {
297       // 创建组件并挂载
298       // 1:创建List组件。
299       auto list = std::make_shared<ArkUIListNode>();
300       list->SetPercentWidth(1);
301       list->SetPercentHeight(1);
302       // 2:创建ListItem懒加载组件并挂载到List上。
303       auto adapter = std::make_shared<ArkUIListItemAdapter>();
304       list->SetLazyAdapter(adapter);
305       return list;
306   }
307   } // namespace NativeModule
308
309   #endif // MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
310   ```
311
3123. 在NativeEntry.cpp中调用List使用懒加载的示例代码。
313   ```c++
314   // NDK接口入口挂载文件。
315
316   #include "NativeEntry.h"
317
318   #include "ArkUIMixedRefresh.h"
319   #include "LazyTextListExample.h"
320   #include "MixedRefreshExample.h"
321   #include "TextListExample.h"
322
323   #include <arkui/native_node_napi.h>
324   #include <arkui/native_type.h>
325   #include <js_native_api.h>
326   #include <uv.h>
327
328   namespace NativeModule {
329
330
331   napi_value CreateNativeRoot(napi_env env, napi_callback_info info) {
332       size_t argc = 1;
333       napi_value args[1] = {nullptr};
334
335       napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
336
337       // 获取NodeContent
338       ArkUI_NodeContentHandle contentHandle;
339       OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
340       NativeEntry::GetInstance()->SetContentHandle(contentHandle);
341
342       // 创建懒加载文本列表
343       auto node = CreateLazyTextListExample(env);
344
345       // 保持Native侧对象到管理类中,维护生命周期。
346       NativeEntry::GetInstance()->SetRootNode(node);
347       g_env = env;
348       return nullptr;
349   }
350
351   napi_value DestroyNativeRoot(napi_env env, napi_callback_info info) {
352       // 从管理类中释放Native侧对象。
353       NativeEntry::GetInstance()->DisposeRootNode();
354       return nullptr;
355   }
356
357   } // namespace NativeModule
358   ```
359## 控制列表滚动位置
360
3611. 控制列表滚动到指定偏移量位置。
362    ```c++
363    //ArkUIListNode.h
364    //列表封装对象。
365    class ArkUIListNode: public ArkUINode {
366        //...
367        void ScrollTo(float offset) {
368            ArkUI_NumberValue value[] = {{.f32 =0},{.f32 = offset},{.f32 = 0}};
369            ArkUI_AttributeItem Item = {.value = value,.size = 3};
370            nativeModule_->setAttribute(handle_, NODE_SCROLL_OFFSET, &Item);
371        }
372    };
373    ```
3742. 控制列表滚动到指定元素。
375    ```c++
376    //ArkUIListNode.h
377    //列表封装对象。
378    class ArkUIListNode : public ArkUINode {
379        //...
380        void ScrollToIndex(int32_t index) {
381            ArkUI_NumberValue value[] = {{.i32 = index}};
382            ArkUI_AttributeItem Item = {.value = value, .size = 1};
383            nativeModule_->setAttribute(handle_, NODE_LIST_SCROLL_TO_INDEX, &Item);
384        }
385    };
386    ```
387
3883. 控制列表滚动指定偏移量。
389    ```c++
390   //ArkUIListNode.h
391    //列表封装对象。
392    class ArkUIListNode : public ArkUINode {
393        void ScrollBy(float offset) {
394            ArkUI_NumberValue value[] = {{.f32 =0},{.f32 = offset}};
395            ArkUI_AttributeItem Item = {.value = value, .size = 2};
396            nativeModule_->setAttribute(handle_, NODE_SCROLL_BY, &Item);
397        }
398    };
399    ```
400## ListItem横划删除
401
4021. ListItem设置NODE_LIST_ITEM_SWIPE_ACTION属性,将ArkUI_ListItemSwipeActionOption对象作为属性参数传入。
403    ```c++
404    // ArkUIListItemNode.h
405    //提供列表项的封装类。
406    #ifndef MYAPPLICATION ARKUISTACKNODE_H
407    #define MYAPPLICATION ARKUISTACKNODE_H
408    #include "ArkUINode.h"
409    namespace NativeModule{
410    class ArkUIListItemNode : public ArkUINode {
411    public:
412        ArkUIListItemNode()
413            : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST_ITEM)) {}
414        ~ArkUIListItemNode() {
415            if(swipeAction_) {
416                OH_ArkUI_ListItemSwipeActionOption_Dispose(swipeAction_);
417            }
418            if (swipeItem_) {
419                OH_ArkUI_ListItemSwipeActionItem_Dispose(swipeItem_);
420            }
421        }
422        void SetSwiperAction(std::shared_ptr<ArkUINode> node) {
423            swipeContent_ = node;
424            swipeItem_ = OH_ArkUI_ListItemSwipeActionItem_Create();
425            OH_ArkUI_ListItemSwipeActionItem_SetContent(swipeItem_, node->GetHandle());
426            swipeAction_ = OH_ArkUI_ListItemSwipeActionOption_Create();
427            OH_ArkUI_ListItemSwipeActionOption_SetEnd(swipeAction_, swipeItem_);
428            ArkUI_AttributeItem Item = {.object= swipeAction_ };
429            nativeModule_->setAttribute(handle_,NODE_LIST_ITEM_SWIPE_ACTION, &Item);
430        }
431        std::shared_ptr<ArkUINode> GetSwipeContent() const {
432            return swipeContent_;
433        }
434    private:
435        ArkUI_ListItemSwipeActionOption* swipeAction_ = nullptr;
436        ArkUI_ListItemSwipeActionItem* swipeItem_ = nullptr;
437        std::shared_ptr<ArkUINode> swipeContent_ = nullptr;
438    };
439    }// namespace NativeModule
440    #endif// MYAPPLICATION_ARKUISTACKNODE_H
441    ```
442
4432. 创建ListItem时,创建ListItem的划出组件,并绑定点击事件,在点击事件中执行删除数据源操作。ListItem复用时,更新划出组件的绑定事件。
444    ```c++
445    // ArkUIListItemAdapter.h
446    class ArkUIListItemAdapter {
447        //...
448        //需要新的Item显示在可见区域。
449        void OnNewItemAttached(ArkUI_NodeAdapterEvent *event) {
450            auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event);
451            ArkUI_NodeHandle handle = nullptr;
452            if (!cachedItems_.empty()) {
453                //使用并更新回收复用的缓存。
454                auto recycledItem = cachedItems_.top();
455                auto textItem = std::dynamic_pointer_cast<ArkUITextNode>(recycledItem->GetChildren().back());
456                textItem->SetTextContent(data_[index]);
457                handle = recycledItem->GetHandle();
458                auto swipeContent = recycledItem->GetSwipeContent();
459                swipeContent->RegisterOnClick([this, data = data_[index]]() {
460                    auto it = std::find(data_.begin(), data_.end(), data);
461                    if (it != data_.end()) {
462                        auto index = std::distance(data_.begin(), it);
463                        RemoveItem(index);
464                    }
465                });
466                //释放缓存池的引用。
467                cachedItems_.pop();
468            } else {
469                //创建新的元素。
470                auto listItem = std::make_shared<ArkUIListItemNode>();
471                auto textNode = std::make_shared<ArkUITextNode>();
472                textNode->SetTextContent(data_[index]);
473                textNode->SetFontSize(16);
474                textNode->SetPercentWidth(1);
475                textNode->SetHeight(100);
476                textNode->SetBackgroundColor(0xFFfffacd);
477                textNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
478                listItem->AddChild(textNode);
479                //创建ListItem划出菜单。
480                auto swipeNode = std::make_shared<ArkUITextNode>();
481                swipeNode->SetTextContent("del");
482                swipeNode->SetFontSize(16);
483                swipeNode->SetFontColor(0xFFFFFFFF);
484                swipeNode->SetWidth(100);
485                swipeNode->SetHeight(100);
486                swipeNode->SetBackgroundColor(0xFFFF0000);
487                swipeNode->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
488                swipeNode->RegisterOnClick([this, data = data_[index]]() {
489                    auto it = std::find(data_.begin(), data_.end(), data);
490                    if (it != data_.end()) {
491                        auto index = std::distance(data_.begin(), it);
492                        RemoveItem(index);
493                    }
494                });
495                listItem->SetSwiperAction(swipeNode);
496                handle = listItem->GetHandle();
497                //保持文本列表项的引用。
498                items_.emplace(handle, listItem);
499            }
500            //设置需要展示的元素。
501            OH_ArkUI_NodeAdapterEvent_SetItem(event, handle);
502        }
503    }
504    ```
5053. ArkUIListItemAdapter中新增RemoveItem,用于删除数据源并且调用OH_ArkUI_NodeAdapter_RemoveItem接口通知框架刷新UI。
506    ```c++
507    // ArkUIListItemAdapter.h
508    class ArkUIListItemAdapter {
509        //...
510        void RemoveItem(size_t index) {
511            //删除第index个数据。
512            data_.erase(data_.begin() + index);
513            //如果index会导致可视区域元素发生可见性变化,则会回调NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_DAPTER事件删除元素,
514            //根据是否有新增元素回调NODE_ADAPTER_EVENT_ON_GET_NODE_ID和NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER事件。
515            OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1);
516            //更新新的数量。
517            OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
518        }
519    };
520    ```
521## 使用分组列表
5221. 分组列表使用ListItemGroup组件实现,ListItemGroup支持添加header、footer设置函数,支持使用懒加载。
523    ```c++
524    // ArkUIListItemGroupNode.h
525
526    #ifndef MYAPPLICATION_ARKUILISTITEMGROUPNODE_H
527    #define MYAPPLICATION_ARKUILISTITEMGROUPNODE_H
528    #include "ArkUINode.h"
529    #include "ArkUIListItemAdapter.h"
530    namespace NativeModule{
531    class ArkUIListItemGroupNode : public ArkUINode {
532    public:
533        ArkUIListItemGroupNode()
534            : ArkUINode((NativeModuleInstance::GetInstance()->GetNativeNodeAPI())->createNode(ARKUI_NODE_LIST_ITEM_GROUP)) {}
535        void SetHeader(std::shared_ptr<ArkUINode> node) {
536            if (node) {
537                ArkUI_AttributeItem Item = {.object = node->GetHandle()};
538                nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_HEADER, &Item);
539            } else {
540                nativeModule_->resetAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_HEADER);
541            }
542        }
543        void SetFooter(std::shared_ptr<ArkUINode> node) {
544            if (node) {
545                ArkUI_AttributeItem Item = {.object= node->GetHandle()};
546                nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_FOOTER, &Item);
547            } else {
548                nativeModule_->resetAttribute(handle_, NODE_LIST_ITEM_GROUP_SET_FOOTER);
549            }
550        }
551        std::shared_ptr<ArkUINode> GetHeader() const {
552            return header_;
553        }
554        std::shared_ptr<ArkUINode> GetFooter() const {
555            return footer_;
556        }
557        //引入懒加载模块。
558        void SetLazyAdapter(const std::shared_ptr<ArkUIListItemAdapter> &adapter) {
559            assert(handle_);
560            ArkUI_AttributeItem item{nullptr,0, nullptr, adapter->GetHandle()};
561            nativeModule_->setAttribute(handle_, NODE_LIST_ITEM_GROUP_NODE_ADAPTER, &item);
562            adapter_ = adapter;
563        }
564    private:
565        std::shared_ptr<ArkUINode> header_;
566        std::shared_ptr<ArkUINode> footer_;
567        std::shared_ptr<ArkUIListItemAdapter> adapter_;
568    };
569    }// namespace NativeModule
570    #endif//MYAPPLICATION_ARKUILISTITEMGROUPNODE_H
571    ```
5722. List组件设置吸顶。
573    ```c++
574    // ArkUIListNode.h
575    //列表封装对象。
576    class ArkUIListNode : public ArkUINode{
577        //...
578        void SetSticky(ArkUI_StickyStyle style) {
579            assert(handle_);
580            ArkUI_NumberValue value[] = {{.i32 = style}};
581            ArkUI_AttributeItem item = {value, 1};
582            nativeModule_->setAttribute(handle_, NODE_LIST_STICKY, &item);
583        }
584    };
585    ```
5863. List组件下使用ListItemGroup实现分组列表界面。
587    ```c++
588    // LazyTextListExample.h
589    //懒加载列表示例代码。
590    #ifndef MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
591    #define MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
592    #include "ArkUIBaseNode.h"
593    #include "ArkUIListNode.h"
594    #include "ArkUIListItemGroupNode.h"
595    namespace NativeModule {
596    std::shared_ptr<ArkUIBaseNode> CreateLazyTextListExample() {
597    //创建组件并挂载
598    //1: 创建List组件。
599        auto list = std::make_shared<ArkUIListNode>();
600        list->SetPercentWidth(1);
601        list->SetPercentHeight(1);
602        //设置吸顶
603        list->SetSticky(ARKUI_STICKY_STYLE_BOTH);
604        //2: 创建ListItemGroup并挂载到List上。
605        for (int32_t i = 0; i < 3; i++) {
606            auto header = std::make_shared<ArkUITextNode>();
607            header->SetTextContent("header");
608            header->SetFontSize(16);
609            header->SetPercentWidth(1);
610            header->SetHeight(50);
611            header->SetBackgroundColor(0xFFDCDCDC);
612            header->SetTextAlign(ARKUI_TEXT_ALIGNMENT_CENTER);
613            auto listItemGroup = std::make_shared<ArkUIListItemGroupNode>();
614            listItemGroup->SetHeader(header);
615            auto adapter = std::make_shared<ArkUIListItemAdapter>(4);
616            listItemGroup->SetLazyAdapter(adapter);
617            list->AddChild(listItemGroup);
618        }
619        return list;
620    }
621    }// namespace NativeModule
622    #endif// MYAPPLICATION_LAZYTEXTLISTEXAMPLE_H
623    ```
624
625
626