目錄
引言
1.List組件基礎
2.List接口參數
?1.space
2.initialIndex
3.scroller
3.ListView的屬性? ? ? ??
1.listDirection
2.lanes
3.divider
4.scrollBar
4.布局與約束
5.ListItem生命周期
1.使用ForEach創建ListItem
2.使用LazyForEach創建ListItem????????
3.使用Repeat創建ListItem
1.使用virtualScroll
2.不使用virtualScroll
6.List的使用場景
1. 最簡單的List
2. 自定義組件
3. 滾動控制
高級特性
1. 分組列表
2. 懶加載
3. 下拉刷新與上拉加載
性能優化技巧
常見問題解決
結語
引言
????????在鴻蒙(HarmonyOS)應用開發中,List組件是最常用的UI組件之一,用于展示垂直滾動的列表數據。本文將詳細介紹List組件的特性、使用方法以及一些實用技巧。
1.List組件基礎
????????列表是一種復雜的容器,當列表項達到一定數量,內容超過屏幕大小時,可以自動提供滾動功能。它適合用于呈現同類數據類型或數據類型集,例如圖片和文本。在列表中顯示數據集合是許多應用程序中的常見要求(如通訊錄、音樂列表、購物清單等)。
????????List是鴻蒙OS中用于展示垂直滾動列表的容器組件,具有以下特點:
-
高性能的列表渲染
-
支持大數據量的流暢滾動
-
內置多種布局和交互效果
-
支持分組和多種列表項樣式
2.List接口參數
??? 當我們創建 List 的時候,有三個默認可選參數,分別是 space、initialIndex、scroller。
? ? 我們分別看看他們的屬性。
?1.space
? ? ? ? space 用來設置子組件主軸方向的間隔。
?圖1.space屬性
2.initialIndex
????????設置當前 List初次加載的時候,初始 item 的索引值。
圖2.修改初次加載顯示的數據元素下標
3.scroller
? ? ? ? 可以滾動組件的控制器。
? ? ? ? 我們可以調用scroll的相關方法處理List。
? ? ? ? 例如我們可以通過下面的代碼把List滾動到底部
Button("滾動到底部").onClick(()=>{this.scroller.scrollEdge(Edge.Bottom)})
3.ListView的屬性? ? ? ??
1.listDirection
????????設置List組件的排列方向。
? ? ? ? listDirection是Axis類型的枚舉,定義如下:
declare enum Axis {
??? Vertical,
??? Horizontal
}? ? ? ??
? ? ? ? 默認值為Axis.Vertical,方向為縱向。
? ? ? ? Axis.Horizontal方向為橫向。
2.lanes
? ? ? ? 設置List組件的布局列數或者行數。
????????lanes
是鴻蒙(HarmonyOS)中List組件的一個重要屬性,用于控制列表在水平方向上的布局方式,特別適用于需要多列布局的場景。通過設置lanes屬性,可以讓List組件中的列表項以網格形式排列,而不是傳統的單列垂直排列。
3.divider
? ? ? ? 設置ListItem分割線樣式,默認無分割線。
4.scrollBar
? ? ? ? 設置滾動條狀態。
????????BarState.AutoAuto:按需顯示
? ? ? ? BarState.AutoOff:不顯示
? ? ? ? BarState.AutoOn:常駐顯示
4.布局與約束
????????列表作為一種容器,會自動按其滾動方向排列子組件,向列表中添加組件或從列表中移除組件會重新排列子組件。
????????如下圖所示,在垂直列表中,List按垂直方向自動排列ListItemGroup或ListItem。
ListItemGroup用于列表數據的分組展示,其子組件也是ListItem。ListItem表示單個列表項,可以包含單個子組件。
圖3.List、ListItemGroup和ListItem組件關系
5.ListItem生命周期
1.使用ForEach創建ListItem
????????List組件創建時,所有ListItem將會被創建。顯示區域內的ListItem在首幀進行布局,預加載范圍內的ListItem在空閑時完成布局。預加載范圍之外的ListItem僅創建ListItem自身,ListItem其內部的子組件不會被創建。
????????當List組件滑動時,進入預加載及顯示區域的ListItem將會創建其內部的子組件并完成布局,而滑出預加載及顯示區域的ListItem將不會被銷毀。
圖4.ForEach創建ListItem
2.使用LazyForEach創建ListItem????????
????????List組件創建時,顯示區域中的ListItem會被創建與布局。預加載范圍內的ListItem在空閑時創建與布局,但是不會被掛載到組件樹上。預加載范圍外的ListItem則不會被創建。
????????當List組件滑動時,進入預加載及顯示區域的ListItem將被創建與布局,創建ListItem過程中,若ListItem內部如果包含@Reusable標記的自定義組件,則會優先從緩存池中復用。滑出預加載及顯示區域的ListItem將被銷毀,其內部若含@Reusable標記的自定義組件,則會被回收并加入緩存池。
圖5.LazyForEach創建ListItem的生命周期
3.使用Repeat創建ListItem
1.使用virtualScroll
????????List組件創建時,顯示區域內的ListItem將被創建和布局。預加載范圍內的ListItem在空閑時創建和布局,并且掛載至組件樹上。預加載范圍外的ListItem則不會被創建。
????????當List組件滑動時,進入預加載及顯示區域的ListItem,將從緩存池中獲取ListItem并復用及布局,若緩存池中無ListItem,則會新創建并布局。滑出預加載及顯示區域的ListItem會將被回收至緩存池。
? ? ? ? 圖6.Repeat使用virtualScroll創建ListItem的生命周期
2.不使用virtualScroll
????????List組件創建時,所有ListItem均被創建。顯示區域內的ListItem在首幀完成布局,預加載范圍內的ListItem在空閑時完成布局。預加載范圍外的ListItem不會進行布局。
????????當List組件滑動時,進入預加載及顯示區域的ListItem將進行布局。滑出預加載及顯示區域的ListItem不會銷毀。
圖7.Repeat不使用virtualScroll創建ListItem的生命周期
1.listDirection
1.listDirection
// 示例代碼:基本List使用
import { List, ListItem } from '@ohos/arkui';@Entry
@Component
struct MyList {private data: string[] = ['蘋果', '香蕉', '橙子', '葡萄', '西瓜']build() {Column() {List({ space: 20 }) {ForEach(this.data, (item: string) => {ListItem() {Text(item).fontSize(20).margin({ left: 15 })}})}.width('100%').height('100%')}}
}
6.List的使用場景
1. 最簡單的List
????????在最簡單的列表形式中,List靜態地創建其列表項ListItem的內容。
? ? ? ? 當我們ListView的ListItem只有一個組件的時候,我們使用下面的代碼即可實現一個簡單的列表。
@Entry
@Component
struct CityList {build() {NavDestination(){List() {ListItem(){Text('北京').fontSize(24)}ListItem(){Text('上海').fontSize(24)}ListItem(){Text('杭州').fontSize(24)}} .backgroundColor('#FFF1F3F5').alignListItem(ListItemAlign.Center)}.title("List實現城市列表")}
}
? ? ? ? 效果圖如下:
圖8.最簡單的List
@State private messages: Message[] = [{ id: 1, content: '你好鴻蒙' },{ id: 2, content: 'List組件學習' },// 更多數據...
];List() {ForEach(this.messages, (item: Message) => {ListItem() {Text(item.content)}})
}
2. 自定義組件
????????因此,如果ListItem是由多個組件元素組成的,則需要將這多個元素組合到一個容器組件內或組成一個自定義組件。
? ? ? ? 例如我們要實現一個通訊錄聯系人頁面:
圖9.聯系人列表
????????如上圖所示,聯系人列表的列表項中,每個聯系人都有頭像和名稱。此時,需要將Image和Text封裝到一個Row容器內。
List() {ListItem() {Row() {// app.media.iconE為自定義資源Image($r('app.media.iconE')).width(40).height(40).margin(10)Text('小明').fontSize(20)}}ListItem() {Row() {// app.media.iconF為自定義資源Image($r('app.media.iconF')).width(40).height(40).margin(10)Text('小紅').fontSize(20)}}
}
3. 滾動控制
private scroller: Scroller = new Scroller()List({ scroller: this.scroller }) {// 列表內容
}// 滾動到指定位置
this.scroller.scrollTo({ x: 0, y: 100 })
高級特性
1. 分組列表
List() {ForEach(this.groupData, (group: Group) => {ListItemGroup({ header: this.GroupHeader(group.name) }) {ForEach(group.items, (item: Item) => {ListItem() {Text(item.name)}})}})
}
2. 懶加載
List() {LazyForEach(this.dataSource, (item: Item) => {ListItem() {Text(item.name)}})
}
3. 下拉刷新與上拉加載
List({ controller: this.listController }) {// 列表內容
}
.onRefresh(() => {// 下拉刷新邏輯
})
.onReachEnd(() => {// 上拉加載更多
})
性能優化技巧
-
?復用列表項?:確保ListItem的結構盡可能簡單,提高復用率
-
?避免復雜計算?:在列表渲染中避免復雜的計算和頻繁的UI更新
-
?使用LazyForEach?:對于大數據集,使用LazyForEach代替ForEach
-
?圖片懶加載?:列表中的圖片使用懶加載技術
常見問題解決
-
?列表滾動卡頓?:
-
檢查是否有過多的UI更新
-
確保使用了正確的數據綁定方式
-
考慮分頁加載數據
-
-
?列表項點擊無響應?:
-
檢查是否添加了.onClick事件
-
確保沒有其他組件遮擋了點擊區域
-
-
?列表數據顯示異常?:
-
檢查數據源是否正確更新
-
確認ForEach或LazyForEach的key值唯一且穩定
-
結語
List組件是鴻蒙應用開發中不可或缺的重要組件,掌握其使用方法和優化技巧對于構建流暢的用戶界面至關重要。通過本文的介紹,希望您能更高效地使用List組件,為您的鴻蒙應用帶來更好的用戶體驗。
在實際開發中,建議多參考鴻蒙官方文檔和示例代碼,不斷實踐和優化您的列表實現。