介紹
主要介紹了滑動(dòng)容器組件Swiper的幾種常見(jiàn)的應(yīng)用場(chǎng)景,包括頂部導(dǎo)航、輪播圖以及視頻滑動(dòng)播放。
相關(guān)概念
- [Swiper]:滑動(dòng)容器,提供子組件切換滑動(dòng)的能力。
- [Stack]:堆疊容器,子組件按照順序依次入棧,后入棧組件在先入棧組件上方顯示。
- [Video]:視頻播放組件。
- [Observed和ObjectLink數(shù)據(jù)管理]:
- @Observed應(yīng)用于類,表示該類中的數(shù)據(jù)變更被UI頁(yè)面管理,例如:@Observed class ClassA {}。
- @ObjectLink應(yīng)用于被@Observed所裝飾類的對(duì)象,例如:@ObjectLink a: ClassA。
環(huán)境搭建
軟件要求
- [DevEco Studio]版本:DevEco Studio 3.1 Release。
- OpenHarmony SDK版本:API version 9。
硬件要求
- 開(kāi)發(fā)板類型:[潤(rùn)和RK3568開(kāi)發(fā)板]。
- OpenHarmony系統(tǒng):3.2 Release。
環(huán)境搭建
完成本篇Codelab我們首先要完成開(kāi)發(fā)環(huán)境的搭建,本示例以RK3568開(kāi)發(fā)板為例,參照以下步驟進(jìn)行:
- [獲取OpenHarmony系統(tǒng)版本]:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。以3.2 Release版本為例:
- 搭建燒錄環(huán)境。
- [完成DevEco Device Tool的安裝]
- [完成RK3568開(kāi)發(fā)板的燒錄](méi)
- 搭建開(kāi)發(fā)環(huán)境。
代碼結(jié)構(gòu)解讀
本篇Codelab只對(duì)核心代碼進(jìn)行講解,完整代碼可以直接從gitee獲取。
├──entry/src/main/ets // 代碼區(qū)
│ ├──common
│ │ └──constants
│ │ ├──CommonConstant.ets // 公共常量
│ │ ├──PictureConstants.ets // 圖片所使用的常量
│ │ ├──TopBarConstants.ets // TopBar使用的常量
│ │ └──VideoConstants.ets // Video使用的常量
│ ├──entryability
│ │ └──EntryAbility.ts // 程序入口類
│ ├──pages
│ │ ├──PageVideo.ets // 視頻播放頁(yè)
│ │ └──SwiperIndex.ets // 應(yīng)用首頁(yè)
│ ├──view
│ │ ├──all
│ │ │ └──PictureSort.ets // “全部”tab頁(yè)圖片類別組件
│ │ ├──common
│ │ │ ├──Banner.ets // 輪播圖組件
│ │ │ ├──PictureView.ets // 圖片組件
│ │ │ └──TopBar.ets // 頂部導(dǎo)航組件
│ │ ├──movie
│ │ │ └──MovieSort.ets // “電影”tab頁(yè)圖片類別組件
│ │ ├──play // 視頻播放組件目錄
│ │ │ ├──CommentView.ets // 評(píng)論模塊組件
│ │ │ ├──DescriptionView.ets // 視頻描述信息組件
│ │ │ ├──NavigationView.ets // 頂部返回導(dǎo)航組件
│ │ │ └──PlayView.ets // 視頻滑動(dòng)播放組件
│ │ └──tabcontent // tab內(nèi)容組件
│ │ ├──PageAll.ets // 全部tab頁(yè)
│ │ ├──PageEntertainment.ets // 娛樂(lè)tab頁(yè)
│ │ ├──PageGame.ets // 游戲tab頁(yè)
│ │ ├──PageLive.ets // 直播tab頁(yè)
│ │ ├──PageMovie.ets // 電影tab頁(yè)
│ │ └──PageTV.ets // 電視tab頁(yè)
│ └──viewmodel
│ ├──PictureItem.ets // 圖片對(duì)象
│ ├──PictureViewModel.ets // 圖片模型
│ ├──TopBarItem.ets // 頂部導(dǎo)航對(duì)象
│ ├──TopBarViewModel.ets // 頂部導(dǎo)航模型
│ ├──VideoItem.ets // 視頻對(duì)象
│ └──VideoViewModel.ets // 視頻模型
└──entry/src/main/resources // 應(yīng)用資源目錄
`HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
頂部導(dǎo)航場(chǎng)景
應(yīng)用首頁(yè)首頁(yè)使用Swiper組件實(shí)現(xiàn)了頂部導(dǎo)航的應(yīng)用場(chǎng)景。用戶點(diǎn)擊不同的分類標(biāo)題,會(huì)切換展示不同的界面內(nèi)容。同時(shí)也支持用戶左右滑動(dòng)界面,對(duì)應(yīng)導(dǎo)航標(biāo)題聯(lián)動(dòng)變化的效果。
實(shí)現(xiàn)這種效果,我們只需將界面劃分為兩部分:導(dǎo)航欄與內(nèi)容區(qū)。導(dǎo)航欄使用自定義組件TopBar實(shí)現(xiàn),內(nèi)容區(qū)使用Swiper組件實(shí)現(xiàn)。
@State和@Link裝飾符配合使用,實(shí)現(xiàn)TopBar組件標(biāo)題與Swiper組件索引的雙向綁定。內(nèi)容區(qū)內(nèi)容滑動(dòng)時(shí),會(huì)觸發(fā)Swiper的onChange事件,并改變索引index的值。前面已經(jīng)通過(guò)特定修飾符實(shí)現(xiàn)了索引的雙向綁定。因此該索引值的變化會(huì)使TopBar的索引值同步變化,實(shí)現(xiàn)TopBar和Swiper的聯(lián)動(dòng)效果。
// SwiperIndex.ets
struct SwiperIndex {
// 索引值雙向綁定 實(shí)現(xiàn)聯(lián)動(dòng)效果.
@State index: number = 0;
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start }) {
TopBar({ index: $index })
Swiper() {
PageAll()
PageMovie()
PageTV()
PageEntertainment()
PageLive()
PageGame()
}
.index(this.index)
.indicator(false)
.loop(false)
.onChange((index: number) = > {
this.index = index;
})
}
.backgroundColor($r('app.color.start_window_background'))
}
}
點(diǎn)擊導(dǎo)航欄中的不同標(biāo)題時(shí),會(huì)觸發(fā)TopBar中的onClick事件,并改變對(duì)應(yīng)的索引值。同理,該索引的變化會(huì)使Swiper的索引值同步變化,實(shí)現(xiàn)Swiper和TopBar的聯(lián)動(dòng)效果。
// TopBar.ets
export struct TopBar {
// 索引值雙向綁定 實(shí)現(xiàn)聯(lián)動(dòng)效果
@Link index: number;
private tabArray: Array< TopBarItem > = initializeOnStartup();
build() {
Row({ space: CommonConstants.SPACE_TOP_BAR }) {
ForEach(this.tabArray,
(item: TopBarItem) = > {
Text(item.name)
.fontSize(this.index === item.id ? $r('app.float.font_size_checked') : $r('app.float.font_size_unchecked'))
.fontColor(Color.Black)
.textAlign(TextAlign.Center)
.fontWeight(this.index === item.id ? FontWeight.Bold : FontWeight.Regular)
.onClick(() = > {
this.index = item.id;
})
}, (item: TopBarItem) = > JSON.stringify(item))
}
.margin({ left: CommonConstants.ADS_LEFT })
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.TOP_BAR_HEIGHT)
}
}
最終實(shí)現(xiàn)導(dǎo)航欄與內(nèi)容區(qū)的雙向聯(lián)動(dòng)效果。
輪播圖場(chǎng)景
輪播圖常見(jiàn)于各種應(yīng)用首頁(yè),用于各類信息、資訊的輪番展示。本應(yīng)用使用Swiper組件,同樣實(shí)現(xiàn)了這一能力?!叭俊表?yè)簽的“電影精選”部分,即為一個(gè)電影內(nèi)容的輪播模塊。它可以切換展示不同電影內(nèi)容。
我們將輪播圖模塊定義為一個(gè)自定義組件Banner。在Banner組件創(chuàng)建新實(shí)例時(shí),會(huì)初始化輪播內(nèi)容并開(kāi)啟定時(shí)任務(wù)。定時(shí)任務(wù)通過(guò)調(diào)用swiperController.showNext()方法,控制Swiper組件切換內(nèi)容展示。
// Banner.ets
aboutToAppear() {
// 內(nèi)容數(shù)據(jù)初始化
this.imageArray = initializePictures(PictureType.BANNER);
// 開(kāi)啟定時(shí)輪播
startPlay(this.swiperController);
}
// PictureViewModel.ets
export function startPlay(swiperController: SwiperController) {
let timerId = setInterval(() = > {
swiperController.showNext();
}, CommonConstants.SWIPER_TIME);
timerIds.push(timerId);
}
在Swiper組件內(nèi),將初始化數(shù)據(jù)進(jìn)行循環(huán)渲染。配合開(kāi)啟的定時(shí)任務(wù),循環(huán)播放。
// Banner.ets
build() {
Swiper(this.swiperController) {
ForEach(this.imageArray, (item: PictureItem) = > {
Stack({ alignContent: Alignment.TopStart }) {
Image(item.image)
...
Column() {
Text($r('app.string.movie_classic'))
.textStyle($r('app.float.font_size_description'), CommonConstants.FONT_WEIGHT_LIGHT)
...
Text(item.name)
.textStyle($r('app.float.font_size_title'), CommonConstants.FONT_WEIGHT_BOLD)
}
...
}
.height(CommonConstants.FULL_HEIGHT)
.width(CommonConstants.FULL_WIDTH)
}, (item: PictureItem) = > JSON.stringify(item))
}
...
}
視頻滑動(dòng)播放場(chǎng)景
視頻滑動(dòng)播放是Swiper組件的另一個(gè)常見(jiàn)應(yīng)用場(chǎng)景。點(diǎn)擊應(yīng)用首頁(yè)中的視頻圖片,會(huì)跳轉(zhuǎn)至視頻播放界面。我們可以通過(guò)上下滑動(dòng),切換播放的視頻內(nèi)容。
視頻播放界面通過(guò)函數(shù)initializeOnStartup初始化視頻內(nèi)容。在Swiper組件內(nèi)通過(guò)循環(huán)渲染的方式,將各個(gè)視頻內(nèi)容渲染成自定義組件PlayView。這樣每一個(gè)視頻內(nèi)容就是一個(gè)Swiper的子組件,就可以通過(guò)滑動(dòng)的方式切換播放內(nèi)容。
// PageVideo.ets
build() {
Column() {
Swiper() {
ForEach(this.videoArray, (item: VideoItem, index: number) = > {
PlayView({
index: $index,
pageShow: $pageShow,
item: item,
barPosition: index
});
}, (item: VideoItem) = > JSON.stringify(item))
}
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
.indicator(false)
.loop(false)
.vertical(true)
.onChange((index: number) = > {
this.index = index;
})
}
}
在自定義組件PlayView中,通過(guò)Video來(lái)控制視頻播放。另外,結(jié)合Stack容器組件,在視頻內(nèi)容上疊加點(diǎn)贊、評(píng)論、轉(zhuǎn)發(fā)等內(nèi)容。
// PlayView.ets
build() {
Stack({ alignContent: Alignment.End }) {
Video({
src: this.item.src,
controller: this.videoController
})
.controls(false)
.autoPlay(this.playState === PlayState.START ? true : false)
.objectFit(ImageFit.Fill)
.loop(true)
.height(CommonConstants.WIDTH_VIDEO)
.width(CommonConstants.FULL_WIDTH)
.onClick(() = > {
if (this.playState === PlayState.START) {
this.playState = PlayState.PAUSE;
this.videoController.pause();
} else if (this.playState === PlayState.PAUSE) {
this.playState = PlayState.START;
this.videoController.start();
}
})
NavigationView()
CommentView({ item: this.item })
DescriptionView()
}
.backgroundColor(Color.Black)
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
}
審核編輯 黃宇
-
鴻蒙
+關(guān)注
關(guān)注
57文章
2352瀏覽量
42858 -
HarmonyOS
+關(guān)注
關(guān)注
79文章
1975瀏覽量
30194
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論