介紹
OpenHarmony ArkTS提供了豐富的接口和組件,開發(fā)者可以根據(jù)實(shí)際場景和開發(fā)需求,選用不同的組件和接口。在本篇Codelab中,我們使用Scroll、List以及LazyForEach實(shí)現(xiàn)一個商品列表的頁面,并且擁有下拉刷新,懶加載和到底提示的效果。效果圖如下:
相關(guān)概念
- [Scroll]:可滾動的容器組件,當(dāng)子組件的布局尺寸超過父組件的視口時,內(nèi)容可以滾動。
- [List]:列表包含一系列相同寬度的列表項。適合連續(xù)、多行呈現(xiàn)同類數(shù)據(jù),例如圖片和文本。
- [Tabs]:一種可以通過頁簽進(jìn)行內(nèi)容視圖切換的容器組件,每個頁簽對應(yīng)一個內(nèi)容視圖。
- [LazyForEach]:開發(fā)框架提供數(shù)據(jù)懶加載(LazyForEach組件)從提供的數(shù)據(jù)源中按需迭代數(shù)據(jù),并在每次迭代過程中創(chuàng)建相應(yīng)的組件。
環(huán)境搭建
軟件要求
硬件要求
- 開發(fā)板類型:[潤和RK3568開發(fā)板]。
- OpenHarmony系統(tǒng):3.2 Release。
環(huán)境搭建
完成本篇Codelab我們首先要完成開發(fā)環(huán)境的搭建,本示例以RK3568開發(fā)板為例,參照以下步驟進(jìn)行:
- [獲取OpenHarmony系統(tǒng)版本]:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。以3.2 Release版本為例:
- 搭建燒錄環(huán)境。
- [完成DevEco Device Tool的安裝]
- [完成RK3568開發(fā)板的燒錄]
- 搭建開發(fā)環(huán)境。
代碼結(jié)構(gòu)解讀
本篇Codelab只對核心代碼進(jìn)行講解,完整代碼可以直接從gitee獲取。
├──entry/src/main/ets // 代碼區(qū)
│ ├──common
│ │ └──CommonConstants.ets // 常量集合文件
│ ├──entryability
│ │ └──EntryAbility.ts // 應(yīng)用入口,承載應(yīng)用的生命周期
│ ├──pages
│ │ └──ListIndex.ets // 頁面入口
│ ├──view
│ │ ├──GoodsListComponent.ets // 商品列表組件
│ │ ├──PutDownRefreshLayout.ets // 下拉刷新組件
│ │ └──TabBarsComponent.ets // Tabs組件
│ └──viewmodel
│ ├──InitialData.ets // 初始化數(shù)據(jù)
│ └──ListDataSource.ets // List使用的相關(guān)數(shù)據(jù)加載
└──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屬性實(shí)現(xiàn)頁面的標(biāo)題,Tabs做商品內(nèi)容的分類。示例代碼如下:
// 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'))
頁面分為“精選”、“手機(jī)”、“服飾”、“穿搭”、“家居”五個模塊,由于本篇CodeLab的主要內(nèi)容在“精選”部分,故將“精選”部分單獨(dú)編寫代碼,其余模塊使用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做長列表,實(shí)現(xiàn)Scroll與List的聯(lián)動。具體實(shí)現(xiàn)代碼如下:
// 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)
}
...
商品列表往往數(shù)據(jù)量很多,如果使用ForEach一次性遍歷生成的話,性能不好,所以這里使用LazyForEach進(jìn)行數(shù)據(jù)的懶加載。當(dāng)向下滑動時,需要加載新的數(shù)據(jù)的時候,再將新的數(shù)據(jù)加載出來,生成新的列表。
通過onTouch事件來觸發(fā)懶加載行為,當(dāng)商品列表向下滑動,加載新的數(shù)據(jù)。示例代碼如下:
// GoodsListComponent.ets
List({ space:commonConst.LIST_ITEM_SPACE }) {
LazyForEach(this.goodsListData, (item: GoodsListItemType) = > {
ListItem() {
Row() {
Column() {
Image(item?.goodsImg)
...
}
... // 布局樣式
Column() {
... // 布局代碼
}
... // 布局樣式
}
}
// 通過Touch事件來觸發(fā)懶加載
.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做下拉的判斷,當(dāng)下拉的偏移量超出將要刷新的偏移量時,就展示下拉刷新的布局,同時使用條件渲染判斷是否顯示下拉刷新布局,實(shí)現(xiàn)效果如下圖:
具體代碼如下:
// TabBarsComponent.ets
putDownRefresh(event?:TouchEvent): void {
if (event === undefined) {
return;
}
switch (event.type) {
case TouchType.Down:
// 記錄手指按下的y坐標(biāo)
this.currentOffsetY = event.touches[0].y;
break;
case TouchType.Move:
// 根據(jù)下拉的偏移量來判斷是否刷新
this.refreshStatus = event.touches[0].y - this.currentOffsetY > MAX_OFFSET_Y;
break;
case TouchType.Cancel:
break;
case TouchType.Up:
// 模擬刷新效果,并未真實(shí)請求數(shù)據(jù)
this.timer = setTimeout(() = > {
this.refreshStatus = false;
}, REFRESH_TIME)
break;
}
}
...
// 下拉刷新的組件根據(jù)條件決定是否顯示
if (this.refreshStatus) {
PutDownRefresh({ refreshText:$refreshText })
}
列表到底提示“已經(jīng)到底了”并回彈的效果使用了Scroll的edgeEffect來控制回彈,實(shí)現(xiàn)效果如下圖:
具體代碼如下:
// 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)
})
審核編輯 黃宇
-
組件
+關(guān)注
關(guān)注
1文章
495瀏覽量
17737 -
鴻蒙
+關(guān)注
關(guān)注
56文章
2267瀏覽量
42493 -
HarmonyOS
+關(guān)注
關(guān)注
79文章
1946瀏覽量
29742 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3549瀏覽量
15746
發(fā)布評論請先 登錄
相關(guān)推薦
評論