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