• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Implementing a List Layout
2
3
4The ArkUI development framework provides list components through NDK APIs, enabling efficient display of structured, scrollable content. List components allow you to control the scroll position, group display content, and use **NodeAdapter** for lazy loading to improve list creation performance.
5
6## Creating a List
7
8For details about how to create a list, see [Integrating with ArkTS Pages](../ui/ndk-access-the-arkts-page.md).
9
10## Listening for Scroll Events
11
12Implement list scroll event monitoring as instructed in the component event monitoring section.
13
14## Implementing Lazy Loading
15
16### NodeAdapter Overview
17
18The NDK provides the [NodeAdapter](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadapterhandle) object as an alternative to the LazyForEach functionality in ArkTS for on-demand generation of child components. **NodeAdapter** works with **List**, **ListItemGroup**, **Grid**, **WaterFlow**, and **Swiper** components.
19
20- Nodes with **NodeAdapter** set do not support direct child addition APIs like **addChild**. Child components are managed entirely by **NodeAdapter**. If a parent component already has child nodes, setting **NodeAdapter** will fail and return an error code.
21
22- **NodeAdapter** notifies you of on-demand generation of components through relevant events. Similar to the component event mechanism, you need to register an [event listener](../reference/apis-arkui/_ark_u_i___native_module.md#oh_arkui_nodeadapter_registereventreceiver) when using **NodeAdapter** and handle logic in the listener events. Relevant events are defined by [ArkUI_NodeAdapterEventType](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadaptereventtype). **NodeAdapter** does not actively release off-screen component objects; you must release or cache and reuse component objects in the [NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER](../reference/apis-arkui/_ark_u_i___native_module.md#arkui_nodeadaptereventtype) event. The following image illustrates the event triggering mechanism in a typical list scrolling scenario.
23  ![en-us_image_0000001949769409](figures/en-us_image_0000001949769409.png)
24
25
26### Implementing a Lazy Loading Adapter
27
28Use the **ArkUListItemAdapter** class to manage the lazy loading adapter. Create a **NodeAdapter** object in the class constructor and set an event listener for the **NodeAdapter** object. In the class destructor, destroy the **NodeAdapter** object.
29
30   ```c++
31   // ArkUIListItemAdapter
32   // Code for lazy loading functionality in a text list.
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()) { // Use the NodeAdapter creation function.
52           // Initialize lazy loading data.
53           for (int32_t i = 0; i < 1000; i++) {
54               data_.emplace_back(std::to_string(i));
55           }
56           // Set lazy loading data.
57           OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
58           // Register the event receiver for lazy loading.
59           OH_ArkUI_NodeAdapter_RegisterEventReceiver(handle_, this, OnStaticAdapterEvent);
60       }
61
62       ~ArkUIListItemAdapter() {
63           // Release created components.
64           while (!cachedItems_.empty()) {
65               cachedItems_.pop();
66           }
67           items_.clear();
68           // Release adapter resources.
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           // Remove the item at the specified index.
77           data_.erase(data_.begin() + index);
78           // If the index change affects the visibility of items in the visible area, the NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER event will be triggered to remove the element.
79           // Depending on whether there are new elements, the NODE_ADAPTER_EVENT_ON_GET_NODE_ID or NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER event will be triggered.
80           OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1);
81           // Update the total count.
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           // If the index change affects the visibility of elements in the visible area, the NODE_ADAPTER_EVENT_ON_GET_NODE_ID and NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER events will be triggered.
88           // If items are removed, the NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER event will be triggered accordingly.
89           OH_ArkUI_NodeAdapter_InsertItem(handle_, index, 1);
90           // Update the total count.
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           // If the move changes the visibility of items within the visible area, the corresponding events will be triggered. Otherwise, no event is triggered.
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           // If the index is within the visible area, first trigger the NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER event to remove the old item,
105           // then trigger the NODE_ADAPTER_EVENT_ON_GET_NODE_ID and NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER events.
106           OH_ArkUI_NodeAdapter_ReloadItem(handle_, index, 1);
107       }
108
109       void ReloadAllItem() {
110           std::reverse(data_.begin(), data_.end());
111           // In the scenario where all items are reloaded, the NODE_ADAPTER_EVENT_ON_GET_NODE_ID event will be triggered to obtain new component IDs,
112           // compare the new component IDs, and reuse those whose IDs have not changed,
113           // for items with new IDs, trigger the NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER event to create new components,
114           // then identify any unused IDs from the old data and call NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER to remove the old items.
115           OH_ArkUI_NodeAdapter_ReloadAllItems(handle_);
116       }
117
118   private:
119       static void OnStaticAdapterEvent(ArkUI_NodeAdapterEvent *event) {
120           // Obtain the instance object and invoke the instance event callback.
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       // Assign IDs to items that need to be displayed, used for element diffing in the ReloadAllItems scenario.
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       // Handle the display of new items in the visible area.
151       void OnNewItemAttached(ArkUI_NodeAdapterEvent *event) {
152           auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event);
153           ArkUI_NodeHandle handle = nullptr;
154           if (!cachedItems_.empty()) {
155               // Use and update the recycled item from the cache.
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               // Release the reference in the cache pool.
161               cachedItems_.pop();
162           } else {
163               // Create an element.
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               // Maintain a reference to the text list item.
176               items_.emplace(handle, listItem);
177           }
178           // Set the element to be displayed.
179           OH_ArkUI_NodeAdapterEvent_SetItem(event, handle);
180       }
181
182       // Remove an item from the visible area.
183       void OnItemDetached(ArkUI_NodeAdapterEvent *event) {
184           auto item = OH_ArkUI_NodeAdapterEvent_GetRemovedNode(event);
185           // Place the item in the cache pool for recycling and reuse.
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       // Manage items generated by the NodeAdapter.
195       std::unordered_map<ArkUI_NodeHandle, std::shared_ptr<ArkUIListItemNode>> items_;
196
197       // Manage the component reuse pool.
198       std::stack<std::shared_ptr<ArkUIListItemNode>> cachedItems_;
199   };
200
201   } // namespace NativeModule
202
203   #endif // MYAPPLICATION_ARKUILISTITEMADAPTER_H
204   ```
205
206### Applying the Lazy Loading Adapter in a List
207
2081. Add the **SetLazyAdapter** function in **ArkUIListNode** to set the **NODE_LIST_NODE_ADAPTER** attribute for the list node and pass the **NodeAdapter** as an attribute parameter.
209   ```c++
210   // ArkUIListNode.h
211   // List encapsulation object.
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               // Unload the UI components under the adapter during destruction.
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       // Import the lazy loading module.
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. Create example code for a **List** using lazy loading and call the **SetLazyAdapter** API of the **List** node to set the lazy loading adapter.
283   ```c++
284   // LazyTextListExample
285   // Example code for a lazy loading text list.
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       // Create and mount the component.
298       // 1: Create a List component.
299       auto list = std::make_shared<ArkUIListNode>();
300       list->SetPercentWidth(1);
301       list->SetPercentHeight(1);
302       // 2: Create a ListItem child component for lazy loading and mount it to the List component.
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. Call the **List** lazy loading example code in **NativeEntry.cpp**.
313   ```c++
314   // NDK API entry mounting file.
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       // Obtain NodeContent.
338       ArkUI_NodeContentHandle contentHandle;
339       OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);
340       NativeEntry::GetInstance()->SetContentHandle(contentHandle);
341
342       // Create a lazy loading text list.
343       auto node = CreateLazyTextListExample(env);
344
345       // Keep the native-side object in the management class to maintain its lifecycle.
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       // Release the native-side object from the management class.
353       NativeEntry::GetInstance()->DisposeRootNode();
354       return nullptr;
355   }
356
357   } // namespace NativeModule
358   ```
359## Controlling the List Scroll Position
360
3611. Control the list to scroll to a specified offset position.
362    ```c++
363    //ArkUIListNode.h
364    // List encapsulation object.
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. Control the list to scroll to a specified element.
375    ```c++
376    //ArkUIListNode.h
377    // List encapsulation object.
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. Control the list to scroll by a specified offset.
389    ```c++
390   //ArkUIListNode.h
391    // List encapsulation object.
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## Implementing Swipe-to-Delete for List Items
401
4021. Set the **NODE_LIST_ITEM_SWIPE_ACTION** attribute for **ListItem** and pass the **ArkUI_ListItemSwipeActionOption** object as an attribute parameter.
403    ```c++
404    // ArkUIListItemNode.h
405    // Encapsulation class for list items.
406    #ifndef MYAPPLICATION_ARKUILISTITEMNODE_H
407    #define MYAPPLICATION_ARKUILISTITEMNODE_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_ARKUILISTITEMNODE_H
441    ```
442
4432. When creating a **ListItem**, create the swipe action item for the **ListItem** and bind a click event to perform the data source deletion operation in the click event. When reusing a **ListItem**, update the binding event of the swipe action item.
444    ```c++
445    // ArkUIListItemAdapter.h
446    class ArkUIListItemAdapter {
447        //...
448        // Handle the display of new items in the visible area.
449        void OnNewItemAttached(ArkUI_NodeAdapterEvent *event) {
450            auto index = OH_ArkUI_NodeAdapterEvent_GetItemIndex(event);
451            ArkUI_NodeHandle handle = nullptr;
452            if (!cachedItems_.empty()) {
453                // Use and update the recycled cache.
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                // Release the reference in the cache pool.
467                cachedItems_.pop();
468            } else {
469                // Create an element.
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                // Create the swipe action item for the 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                // Maintain a reference to the text list item.
498                items_.emplace(handle, listItem);
499            }
500            // Set the element to be displayed.
501            OH_ArkUI_NodeAdapterEvent_SetItem(event, handle);
502        }
503    }
504    ```
5053. Add **RemoveItem** in **ArkUIListItemAdapter** to delete the data source and call the **OH_ArkUI_NodeAdapter_RemoveItem** API to instruct the framework to update the UI.
506    ```c++
507    // ArkUIListItemAdapter.h
508    class ArkUIListItemAdapter {
509        //...
510        void RemoveItem(size_t index) {
511            // Remove the item at the specified index.
512            data_.erase(data_.begin() + index);
513            // If the index change affects the visibility of items in the visible area, the NODE_ADAPTER_EVENT_ON_REMOVE_NODE_FROM_ADAPTER event will be triggered to remove the element.
514            // Depending on whether there are new elements, the NODE_ADAPTER_EVENT_ON_GET_NODE_ID or NODE_ADAPTER_EVENT_ON_ADD_NODE_TO_ADAPTER event will be triggered.
515            OH_ArkUI_NodeAdapter_RemoveItem(handle_, index, 1);
516            // Update the total count.
517            OH_ArkUI_NodeAdapter_SetTotalNodeCount(handle_, data_.size());
518        }
519    };
520    ```
521## Using a Grouped List
5221. Implement a grouped list using the **ListItemGroup** component, which supports features to add headers and footers and use lazy loading.
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        // Import the lazy loading module.
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. Set the sticky header for the **List** component.
573    ```c++
574    // ArkUIListNode.h
575    // List encapsulation object.
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. Implement a grouped list UI using **ListItemGroup** under the **List** component.
587    ```c++
588    // LazyTextListExample.h
589    // Example code for a lazy loading text list.
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    // Create and mount the component.
598    // 1: Create a List component.
599        auto list = std::make_shared<ArkUIListNode>();
600        list->SetPercentWidth(1);
601        list->SetPercentHeight(1);
602        // Set the sticky header.
603        list->SetSticky(ARKUI_STICKY_STYLE_BOTH);
604        // 2: Create a ListItemGroup and mount it to the 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