介紹
OpenHarmony ArkTS提供了豐富的接口和組件,開發者可以根據實際場景和開發需求,選用不同的組件和接口。在本篇Codelab中,我們使用Scroll、List以及LazyForEach實現一個商品列表的頁面,并且擁有下拉刷新,懶加載和到底提示的效果。效果圖如下:
相關概念
- [Scroll]:可滾動的容器組件,當子組件的布局尺寸超過父組件的視口時,內容可以滾動。
- [List]:列表包含一系列相同寬度的列表項。適合連續、多行呈現同類數據,例如圖片和文本。
- [Tabs]:一種可以通過頁簽進行內容視圖切換的容器組件,每個頁簽對應一個內容視圖。
- [LazyForEach]:開發框架提供數據懶加載(LazyForEach組件)從提供的數據源中按需迭代數據,并在每次迭代過程中創建相應的組件。
環境搭建
軟件要求
硬件要求
- 開發板類型:[潤和RK3568開發板]。
- OpenHarmony系統:3.2 Release。
環境搭建
完成本篇Codelab我們首先要完成開發環境的搭建,本示例以RK3568開發板為例,參照以下步驟進行:
- [獲取OpenHarmony系統版本]:標準系統解決方案(二進制)。以3.2 Release版本為例:
- 搭建燒錄環境。
- [完成DevEco Device Tool的安裝]
- [完成RK3568開發板的燒錄]
- 搭建開發環境。
代碼結構解讀
本篇Codelab只對核心代碼進行講解,完整代碼可以直接從gitee獲取。
├──entry/src/main/ets // 代碼區
│ ├──common
│ │ └──CommonConstants.ets // 常量集合文件
│ ├──entryability
│ │ └──EntryAbility.ts // 應用入口,承載應用的生命周期
│ ├──pages
│ │ └──ListIndex.ets // 頁面入口
│ ├──view
│ │ ├──GoodsListComponent.ets // 商品列表組件
│ │ ├──PutDownRefreshLayout.ets // 下拉刷新組件
│ │ └──TabBarsComponent.ets // Tabs組件
│ └──viewmodel
│ ├──InitialData.ets // 初始化數據
│ └──ListDataSource.ets // List使用的相關數據加載
└──entry/src/main/resources
├──base
│ ├──element // 字符串以及顏色的資源文件
│ ├──media // 圖片等資源文件
│ └──profile // 頁面配置文件存放位置
├──en_US
│ └──element
│ └──string.json // 英文字符存放位置
└──zh_CN
└──element
└──string.json // 中文字符存放位置
`HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
頁面布局
頁面使用Navigation與Tabs做頁面布局,使用Navigation的title屬性實現頁面的標題,Tabs做商品內容的分類。示例代碼如下:
// ListIndex.ets
Row() {
Navigation() {
Column() {
TabBars()
}
.width(LAYOUT_WIDTH_OR_HEIGHT)
.justifyContent(FlexAlign.Center)
}
.size({ width: LAYOUT_WIDTH_OR_HEIGHT, height: LAYOUT_WIDTH_OR_HEIGHT })
.title(STORE)
.titleMode(NavigationTitleMode.Mini)
}
.height(LAYOUT_WIDTH_OR_HEIGHT)
.backgroundColor($r('app.color.primaryBgColor'))
頁面分為“精選”、“手機”、“服飾”、“穿搭”、“家居”五個模塊,由于本篇CodeLab的主要內容在“精選”部分,故將“精選”部分單獨編寫代碼,其余模塊使用ForEach遍歷生成。示例代碼如下:
// TabBarsComponent.ets
Tabs() {
// 精選模塊
TabContent() {
Scroll() {
Column() {
if (this.refreshStatus) {
PutDownRefresh({ refreshText: $refreshText })
}
GoodsList()
Text($r('app.string.to_bottom'))
.fontSize(NORMAL_FONT_SIZE)
.fontColor($r('app.color.gray'))
}
.width(LAYOUT_WIDTH_OR_HEIGHT)
}
...
}
.tabBar(this.firstTabBar)
// 其他模塊
ForEach(initTabBarData, (item: Resource, index?: number) = > {
TabContent() {
Column() {
Text(item).fontSize(MAX_FONT_SIZE)
}
.justifyContent(FlexAlign.Center)
.width(LAYOUT_WIDTH_OR_HEIGHT)
.height(LAYOUT_WIDTH_OR_HEIGHT)
}
.tabBar(this.otherTabBar(item, index !== undefined ? index : 0))
})
}
...
商品列表的懶加載
使用Scroll嵌套List做長列表,實現Scroll與List的聯動。具體實現代碼如下:
// TabBarsComponent.ets
Scroll() {
Column() {
// 下拉刷新的組件
if (this.refreshStatus) {
PutDownRefresh({ refreshText:$refreshText })
}
// List的自定義組件
GoodsList()
Text($r('app.string.to_bottom')).fontSize(NORMAL_FONT_SIZE).fontColor($r('app.color.gray'))
}
.width(LAYOUT_WIDTH_OR_HEIGHT)
}
...
商品列表往往數據量很多,如果使用ForEach一次性遍歷生成的話,性能不好,所以這里使用LazyForEach進行數據的懶加載。當向下滑動時,需要加載新的數據的時候,再將新的數據加載出來,生成新的列表。
通過onTouch事件來觸發懶加載行為,當商品列表向下滑動,加載新的數據。示例代碼如下:
// GoodsListComponent.ets
List({ space:commonConst.LIST_ITEM_SPACE }) {
LazyForEach(this.goodsListData, (item: GoodsListItemType) = > {
ListItem() {
Row() {
Column() {
Image(item?.goodsImg)
...
}
... // 布局樣式
Column() {
... // 布局代碼
}
... // 布局樣式
}
}
// 通過Touch事件來觸發懶加載
.onTouch((event?:TouchEvent) = > {
if (event === undefined) {
return;
}
switch (event.type) {
case TouchType.Down:
this.startTouchOffsetY = event.touches[0].y;
break;
case TouchType.Up:
this.startTouchOffsetY = event.touches[0].y;
break;
case TouchType.Move:
if (this.startTouchOffsetY - this.endTouchOffsetY > 0) {
this.goodsListData.pushData();
}
break;
}
})
})
}
...
下拉刷新與到底提示
下拉刷新同樣使用TouchEvent做下拉的判斷,當下拉的偏移量超出將要刷新的偏移量時,就展示下拉刷新的布局,同時使用條件渲染判斷是否顯示下拉刷新布局,實現效果如下圖:
具體代碼如下:
// TabBarsComponent.ets
putDownRefresh(event?:TouchEvent): void {
if (event === undefined) {
return;
}
switch (event.type) {
case TouchType.Down:
// 記錄手指按下的y坐標
this.currentOffsetY = event.touches[0].y;
break;
case TouchType.Move:
// 根據下拉的偏移量來判斷是否刷新
this.refreshStatus = event.touches[0].y - this.currentOffsetY > MAX_OFFSET_Y;
break;
case TouchType.Cancel:
break;
case TouchType.Up:
// 模擬刷新效果,并未真實請求數據
this.timer = setTimeout(() = > {
this.refreshStatus = false;
}, REFRESH_TIME)
break;
}
}
...
// 下拉刷新的組件根據條件決定是否顯示
if (this.refreshStatus) {
PutDownRefresh({ refreshText:$refreshText })
}
列表到底提示“已經到底了”并回彈的效果使用了Scroll的edgeEffect來控制回彈,實現效果如下圖:
具體代碼如下:
// TabBarsComponent.ets
Scroll() {
Column() {
...
GoodsList()
Text($r('app.string.to_bottom')).fontSize(NORMAL_FONT_SIZE).fontColor($r('app.color.gray'))
}
.width(LAYOUT_WIDTH_OR_HEIGHT)
}
.scrollBar(BarState.Off)
.edgeEffect(EdgeEffect.Spring)
.width(LAYOUT_WIDTH_OR_HEIGHT)
.height(LAYOUT_WIDTH_OR_HEIGHT)
.onTouch((event?: TouchEvent) = > {
this.putDownRefresh(event)
})
審核編輯 黃宇
-
組件
+關注
關注
1文章
505瀏覽量
17806 -
鴻蒙
+關注
關注
57文章
2321瀏覽量
42749 -
HarmonyOS
+關注
關注
79文章
1967瀏覽量
30036 -
OpenHarmony
+關注
關注
25文章
3665瀏覽量
16162
發布評論請先 登錄
相關推薦
評論