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  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