ArkUI Video Playback Tutorial
Code Implementation
Main Page with Swiper
Below is the code for implementing a main page with a Swiper component:
// @ts-nocheck
import { TopBar } from '../view/common/TopBar';
import { PageAll } from '../view/tabcontent/PageAll';
import { CommonConstants } from '../common/constants/CommonConstant';
import { PageEntertainment } from '../view/tabcontent/PageEntertainment';
import { PageMovie } from '../view/tabcontent/PageMovie';
import PageAnime, { PageAnime } from '../view/tabcontent/PageAnime';
import PageTV, { PageTV } from '../view/tabcontent/PageTV';
@Entry
@Component
struct SwiperIndex {
@State index: number = 0;
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start }) {
TopBar({ index: $index });
Swiper() {
PageAll();
PageMovie();
PageTV();
PageEntertainment();
PageAnime();
}
.index(this.index)
.indicator(false)
.loop(false)
.duration(CommonConstants.DURATION_PAGE)
.onChange((index: number) => {
this.index = index;
});
}
.backgroundColor($r('app.color.start_window_background'));
}
}
TopBar Component
Here's the implementation of the TopBar component:
import { TopBarItem } from '../../common/bean/TopBarItem';
import { initializeOnStartup } from '../../viewmodel/TopBarViewModel';
import { CommonConstants } from '../../common/constants/CommonConstant';
@Component
export struct TopBar {
@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 ? CommonConstants.FONT_SIZE_CHECKED : CommonConstants.FONT_SIZE_UNCHECKED)
.fontColor(Color.Black)
.textAlign(TextAlign.Center)
.fontWeight(this.index === item.id ? FontWeight.Bold : FontWeight.Regular)
.onClick(() => {
this.index = item.id;
})
));
}
.margin({ left: CommonConstants.ADS_LEFT })
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.TOP_BAR_HEIGHT);
}
}
TV Page Implementation
Here's the implementation of the TV page:
import { CommonConstants } from '../../common/constants/CommonConstant';
import { PositionDataSource } from '../../viewmodel/PositionDataSource';
@Component
export default struct PageTV {
@Provide positionListData: PositionDataSource = new PositionDataSource();
private startTouchOffsetY: number = 0;
private endTouchOffsetY: number = 0;
private username: String = "";
private title: String = "";
build() {
Row() {
List({ space: CommonConstants.LIST_ITEM_SPACE }) {
LazyForEach(this.positionListData, (item) => (
ListItem() {
Row() {
Column() {
Image(item?.logo)
.width(CommonConstants.LAYOUT_WIDTH_OR_HEIGHT)
.height(CommonConstants.LAYOUT_WIDTH_OR_HEIGHT);
}
.width(CommonConstants.GOODS_IMAGE_WIDTH)
.height(CommonConstants.LAYOUT_WIDTH_OR_HEIGHT);
Column() {
Row() {
Text(item?.name)
.fontSize(CommonConstants.NORMAL_FONT_SIZE)
.margin({ top: CommonConstants.BIGGER_FONT_SIZE });
}
.justifyContent(FlexAlign.Start)
.width(CommonConstants.GOODS_LIST_WIDTH);
Row() {
Text(item?.cname)
.fontColor($r('app.color.black_text_color'))
.fontSize(CommonConstants.GOODS_EVALUATE_FONT_SIZE);
Text(item?.size)
.fontSize(CommonConstants.NORMAL_FONT_SIZE)
.fontColor($r('app.color.login_blue_text_color'))
.margin({ left: 10 });
}
.justifyContent(FlexAlign.Start)
.width(CommonConstants.GOODS_LIST_WIDTH)
.margin({ top: 20 });
Row() {
Text('Time')
.fontSize(CommonConstants.NORMAL_FONT_SIZE)
.fontColor($r('app.color.red'));
Text(item?.salary)
.fontSize(CommonConstants.GOODS_EVALUATE_FONT_SIZE)
.fontColor($r('app.color.login_blue_text_color'))
.margin({ left: 10 });
}
.justifyContent(FlexAlign.Start)
.width(CommonConstants.GOODS_LIST_WIDTH)
.margin({ top: 20 });
}
.padding(CommonConstants.GOODS_LIST_PADDING)
.width(CommonConstants.GOODS_FONT_WIDTH)
.height(CommonConstants.LAYOUT_WIDTH_OR_HEIGHT);
}
.justifyContent(FlexAlign.SpaceBetween)
.height(CommonConstants.GOODS_LIST_HEIGHT)
.width(CommonConstants.LAYOUT_WIDTH_OR_HEIGHT)
.onTouch((event: TouchEvent) => {
switch (event.type) {
case TouchType.Down:
this.startTouchOffsetY = event.touches[0].y;
break;
case TouchType.Move:
this.endTouchOffsetY = event.touches[0].y;
if (this.startTouchOffsetY - this.endTouchOffsetY > 0) {
this.positionListData.pushData();
}
break;
}
});
}
});
}
.width(CommonConstants.GOODS_LIST_WIDTH);
}
.justifyContent(FlexAlign.Center)
.width(CommonConstants.LAYOUT_WIDTH_OR_HEIGHT);
}
}
Sample Data
Here's the code for the sample data:
export interface PositionListItemType {
logo: Resource;
name: Resource;
cname: Resource;
size: Resource;
salary: Resource;
}
export const positionInitialList: PositionListItemType[] = [
{
logo: $r('app.media.fangyandexingxing'),
name: $r('app.string.Entertainmentname1'),
cname: $r('app.string.typesof'),
size: $r('app.string.typesof1'),
salary: $r('app.string.times1'),
},
{
logo: $r('app.media.wohejiangshiyuehui'),
name: $r('app.string.Entertainmentname2'),
cname: $r('app.string.typesof'),
size: $r('app.string.typesof2'),
salary: $r('app.string.times2'),
},
{
logo: $r('app.media.yitiantulongji'),
name: $r('app.string.Entertainmentname3'),
cname: $r('app.string.typesof'),
size: $r('app.string.typesof3'),
salary: $r('app.string.times3'),
},
{
logo: $r('app.media.getoutianwang'),
name: $r('app.string.Entertainmentname4'),
cname: $r('app.string.typesof'),
size: $r('app.string.typesof4'),
salary: $r('app.string.times4'),
},
{
logo: $r('app.media.xianjianqixiazhuna'),
name: $r('app.string.Entertainmentname5'),
cname: $r('app.string.typesof'),
size: $r('app.string.typesof5'),
salary: $r('app.string.times5'),
},
];
Lazy Loading Data Processing
Here's the code for lazy loading data processing:
import { positionInitialList, PositionListItemType } from './PositionData';
const createListRange = () => {
let result = [];
for (let i = 0; i < 2; i++) {
result = [...result, ...positionInitialList];
}
return result;
};
class BasicDataSource implements IDataSource {
private listeners: DataChangeListener[] = [];
public totalCount(): number {
return 0;
}
public getData(index: number): PositionListItemType {
return undefined;
}
public getPositionData(index: number): PositionListItemType {
return undefined;
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
this.listeners.push(listener);
}
}
unregisterDataChangeListener(listener: DataChangeListener): void {
const position = this.listeners.indexOf(listener);
if (position >= 0) {
this.listeners.splice(position, 1);
}
}
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded();
});
}
notifyDataAdd(index: number): void {
this.listeners.forEach(listener => {
listener.onDataAdd(index);
});
}
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index);
});
}
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index);
});
}
notifyDataMove(from: number, to: number): void {
this.listeners.forEach(listener => {
listener.onDataMove(from, to);
});
}
}
export class PositionDataSource extends BasicDataSource {
private listData = createListRange();
public totalCount(): number {
return this.listData.length;
}
public getData(index: number): PositionListItemType {
return this.listData[index];
}
public pushData(): void {
if (this.listData.length < 12) {
this.listData = [...this.listData, ...positionInitialList];
this.notifyDataAdd(this.listData.length - 1);
}
}
}
Explanation
In this tutorial, we have implemented a video playback interface using ArkUI. The main components include:
- SwiperIndex: The main page that integrates the TopBar and Swiper components to achieve a tabbed page switching effect.
- TopBar: A navigation bar component that works with the Swiper component to provide a tabbed navigation experience.
- PageTV: The implementation of the TV show page, which displays a list of TV shows with their details.
- Sample Data: Provides initial data for the TV shows displayed on the PageTV page.
- Lazy Loading Data Processing: Implements data lazy loading to improve performance and user experience.
Top comments (0)