diff --git a/README.en.md b/README.en.md index 024e1d083e5c4589d918a9199a95bb9b728c021a..bc22eec291df86bf4a1a8daf05c90f44e943286c 100644 --- a/README.en.md +++ b/README.en.md @@ -29,11 +29,8 @@ This sample describes how to smoothly refresh a page. │ ├──view │ │ ├──AVPlayerItem.ets // AVPlayer page │ │ ├──ButtonItem.ets // Button item page -│ │ ├──ImageModifier.ets // Image modifier -│ │ ├──MuliGrid.ets // Layout page │ │ ├──SampleUnitAVPlayView.ets // AVPlayer sample page │ │ ├──SampleUnitPicView.ets // Image sample page -│ │ ├──SampleUnitVideoSecondView.ets // Video sample page │ │ ├──SampleUnitVideoView.ets // Video sample page │ │ ├──SampleUnitView.ets // Sample display page │ │ └──TitleAreaItem.ets // Title page diff --git a/README.md b/README.md index e52eb531988e88451f98247f61f6739368786dff..6db4caa36bdfb842c01a4d4a00f691ddfa92718d 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,8 @@ │ ├──view │ │ ├──AVPlayerItem.ets // AVPlayer页 │ │ ├──ButtonItem.ets // Button Item页 -│ │ ├──ImageModifier.ets // 图片页 -│ │ ├──MuliGrid.ets // 布局页 │ │ ├──SampleUnitAVPlayView.ets // AVPlayer样例页 │ │ ├──SampleUnitPicView.ets // 图片样例页 -│ │ ├──SampleUnitVideoSecondView.ets // 视频样例页 │ │ ├──SampleUnitVideoView.ets // 视频样例页 │ │ ├──SampleUnitView.ets // 样例展示页 │ │ └──TitleAreaItem.ets // 标题页 diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index 0c9ff5be3d4856dedac6fcb999ea32f5b1d602ef..5ea101c0ce71cb29eb4159f24f6a77fe9b24a642 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -42,6 +42,7 @@ export default class EntryAbility extends UIAbility { AppStorage.setOrCreate('currentBreakpoint', this.curBp); } } catch (error) { + this.curBp == Constants.BREAK_POINT_SM; hilog.error(0x0000, TAG, 'updateBreakpoint catch err:', JSON.stringify(error) ?? ''); } } @@ -61,10 +62,6 @@ export default class EntryAbility extends UIAbility { } } - onDestroy(): void { - hilog.info(0x0000, TAG, '%{public}s', 'Ability onDestroy'); - } - onWindowStageCreate(windowStage: window.WindowStage): void { windowStage.getMainWindow().then((windowObj: window.Window) => { let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; @@ -86,19 +83,19 @@ export default class EntryAbility extends UIAbility { let context = this.context; let resourceManager: resourceManager.ResourceManager = context.resourceManager; AppStorage.setOrCreate('resourceManager', resourceManager); - windowStage.loadContent('pages/Index', (err, data) => { + windowStage.loadContent('pages/Index', (err, _) => { if (err.code) { - hilog.error(0x0000, TAG, 'Failed to load the content. Cause:', JSON.stringify(err) ?? ''); + hilog.error(0x0000, TAG, 'Failed to load the content. Cause:', JSON.stringify(err.message) ?? ''); return; } - hilog.info(0x0000, TAG, 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + hilog.info(0x0000, TAG, '%{public}s', 'Succeeded in loading the content'); let windowClass: window.Window = windowStage.getMainWindowSync(); let isLayoutFullScreen = true; windowClass.setWindowLayoutFullScreen(isLayoutFullScreen).then(() => { hilog.info(0x0000, TAG, '%{public}s', 'Succeeded in setting the window layout to full-screen mode'); }).catch((err: BusinessError) => { hilog.error(0x0000, TAG, 'Failed to set the window layout to full-screen mode. Cause:', - JSON.stringify(err) ?? ''); + JSON.stringify(err.message) ?? ''); }); }); } diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 5a743ba80d7f2d658e00363b4d2a8a67dd46f56d..97575fb49e0f00c585be8fff83da7ab15db16c1c 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -36,8 +36,6 @@ struct Index { type: item.type, buttonUnit: item.button, imageArray: item.pic, - controller: item.controller, - avPlayer: item.avPlayer }) .padding({ left: new BreakpointType(Constants.PICTURE_GRID_MARGIN[0], Constants.PICTURE_GRID_MARGIN[1], @@ -49,6 +47,7 @@ struct Index { } }, (item: string) => item); } + .cachedCount(2) .margin({ top: px2vp(this.topRectHeight) }) .backgroundColor($r('sys.color.background_secondary')) .scrollBar(BarState.Off) diff --git a/entry/src/main/ets/pages/NewPlayPage.ets b/entry/src/main/ets/pages/NewPlayPage.ets index a6b7f77b8d4a96012034ccc863e0458e9d743c85..add218ac0379a7afb99e817ebdcf6c21d54069af 100644 --- a/entry/src/main/ets/pages/NewPlayPage.ets +++ b/entry/src/main/ets/pages/NewPlayPage.ets @@ -43,6 +43,7 @@ struct NewPlayPage { this.backDisplaySync.stop(); this.backDisplaySync = undefined; } + this.avPlayer.release(); } CreateDisplaySync() { @@ -51,7 +52,7 @@ struct NewPlayPage { min: 0, max: 120 }; - let draw = (intervalInfo: displaySync.IntervalInfo) => { + let draw = () => { if (this.rotateAngle === 360) { this.rotateAngle = 0; } @@ -98,7 +99,7 @@ struct NewPlayPage { .zIndex(2) SampleUnitAVPlayView({ - avPlayer: $avPlayer + avPlayer: this.avPlayer }); Row() { diff --git a/entry/src/main/ets/view/AVPlayerItem.ets b/entry/src/main/ets/view/AVPlayerItem.ets index 2cca8a1812e0b8239af996cfa3f062f429aee201..880452b18d11efce1b29cbbbb8a1940afa34145b 100644 --- a/entry/src/main/ets/view/AVPlayerItem.ets +++ b/entry/src/main/ets/view/AVPlayerItem.ets @@ -33,7 +33,7 @@ export class AVPlayerItem { avPlayer.on('timeUpdate', () => { this.curTime = avPlayer.currentTime / 1000; }) - avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => { + avPlayer.on('stateChange', async (state: string) => { switch (state) { case 'idle': avPlayer.release(); @@ -83,4 +83,11 @@ export class AVPlayerItem { this.avPlayer.fdSrc = avFileDescriptor; this.avPlayer.prepare(); } + + async release() { + if (this.avPlayer) { + this.avPlayer.release(); + this.avPlayer = null; + } + } } \ No newline at end of file diff --git a/entry/src/main/ets/view/ImageModifier.ets b/entry/src/main/ets/view/ImageModifier.ets deleted file mode 100644 index db7aa03a330b3c4db7cc9a432a6693cc3f322019..0000000000000000000000000000000000000000 --- a/entry/src/main/ets/view/ImageModifier.ets +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export class ImageModifier implements AttributeModifier { - private imageFit: ImageFit = ImageFit.Fill; - private imageRenderMode: ImageRenderMode = ImageRenderMode.Original; - - constructor() { - } - - applyNormalAttribute(instance: ImageAttribute): void { - instance.objectFit(this.imageFit); - instance.renderMode(this.imageRenderMode); - } - - objectFit(fit: ImageFit): ImageModifier { - this.imageFit = fit; - return this; - } - - renderMode(mode: ImageRenderMode): ImageModifier { - this.imageRenderMode = mode; - return this; - } -} \ No newline at end of file diff --git a/entry/src/main/ets/view/MultiGrid.ets b/entry/src/main/ets/view/MultiGrid.ets deleted file mode 100644 index 5439845c681996463047bb9898a5c8b76a616418..0000000000000000000000000000000000000000 --- a/entry/src/main/ets/view/MultiGrid.ets +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Constants } from '../common/Constants'; -import { BreakpointType } from '../common/Utils'; - -interface GridConfig { - rows: number, - columns: number, - imageWidth: string -} - -const GRID_GAP: number = 4; -const IMAGE_SET_SIZE_9: number = 9; - -@Component -export struct MultiGrid { - @StorageLink('currentBreakpoint') curBp: string = Constants.BREAK_POINT_SM; - private imageSource: (string | Resource)[] = []; - private arraySize: number = 0; - - aboutToAppear(): void { - this.arraySize = Math.min(this.imageSource.length, IMAGE_SET_SIZE_9); - } - - build() { - Column() { - Grid() { - ForEach(this.imageSource.slice(0, this.arraySize), (item: string | Resource, index: number) => { - GridItem() { - Image(item) - .objectFit(ImageFit.Cover) - .width(new BreakpointType(this.getSmConfig(), this.getMdConfig(), this.getLgConfig()).getValue(this.curBp) - .imageWidth) - .aspectRatio(1) - } - }, (index: number) => index.toString()) - } - .maxCount(new BreakpointType(this.getSmConfig(), this.getMdConfig(), this.getLgConfig()).getValue(this.curBp) - .columns) - .columnsGap(GRID_GAP) - .rowsGap(GRID_GAP) - .width(Constants.FULL_SIZE) - } - } - - private getSmConfig(): GridConfig { - let rows: number; - let columns: number; - if (this.arraySize <= 1) { - rows = 1; - columns = 1; - return { rows, columns, imageWidth: '60%' }; - } else if (this.arraySize === 2) { - rows = 1; - columns = 2; - } else if (this.arraySize === 3) { - rows = 1; - columns = 3; - } else if (this.arraySize === 4) { - rows = 2; - columns = 2; - } else if (this.arraySize <= 6) { - rows = 2; - columns = 3; - } else { - rows = 3; - columns = 3; - } - const imageWidth = `calc((100% - ${GRID_GAP * (columns - 1)}vp) / ${columns})`; - return { rows, columns, imageWidth }; - } - - private getMdConfig(): GridConfig { - let rows: number; - let columns: number; - if (this.arraySize <= 1) { - rows = 1; - columns = 1; - return { rows, columns, imageWidth: '40%' }; - } else if (this.arraySize === 2) { - rows = 1; - columns = 2; - } else if (this.arraySize === 3) { - rows = 1; - columns = 3; - } else if (this.arraySize === 4) { - rows = 2; - columns = 2; - return { rows, columns, imageWidth: '30%' }; - } else if (this.arraySize <= 6) { - rows = 2; - columns = 3; - } else if (this.arraySize <= 8) { - rows = 2; - columns = 4; - } else { - rows = 2; - columns = 5; - } - const imageWidth = `calc((100% - ${GRID_GAP * (columns - 1)}vp) / ${columns})`; - return { rows, columns, imageWidth }; - } - - private getLgConfig(): GridConfig { - let rows: number; - let columns: number; - if (this.arraySize <= 1) { - rows = 1; - columns = 1; - return { rows, columns, imageWidth: '40%' }; - } else if (this.arraySize === 2) { - rows = 1; - columns = 2; - } else if (this.arraySize === 3) { - rows = 1; - columns = 3; - } else if (this.arraySize === 4) { - rows = 1; - columns = 4; - } else if (this.arraySize <= 6) { - rows = 2; - columns = 3; - } else if (this.arraySize <= 8) { - rows = 2; - columns = 4; - } else { - rows = 2; - columns = 5; - } - const imageWidth = `calc((100% - ${GRID_GAP * (columns - 1)}vp) / ${columns})`; - return { rows, columns, imageWidth }; - } -} \ No newline at end of file diff --git a/entry/src/main/ets/view/SampleUnitAVPlayView.ets b/entry/src/main/ets/view/SampleUnitAVPlayView.ets index 64b171b746497dd1e4afd48bbdae8c4454c02fc9..ff0f78277bcdf34ac22627bd241fd34f680ed4c2 100644 --- a/entry/src/main/ets/view/SampleUnitAVPlayView.ets +++ b/entry/src/main/ets/view/SampleUnitAVPlayView.ets @@ -13,23 +13,21 @@ * limitations under the License. */ -import { display } from '@kit.ArkUI'; import { Constants } from '../common/Constants'; import { AVPlayerItem } from '../view/AVPlayerItem'; // Delay time const DELAY = 500; -// Animation duration -const DURATION = 29024; // Surface size -const SURFACE_SIZE = 1500; +const SURFACE_WIDTH = 1600; +const SURFACE_HEIGHT = 900; @Component export default struct SampleUnitAVPlayView { @Link avPlayer: AVPlayerItem; + @StorageLink('currentBreakpoint') curBp: string = Constants.BREAK_POINT_SM; @State xComponentWidth: string = Constants.FULL_SIZE; @State xComponentHeight: string = Constants.FIFTY_SIZE; - @State curTime: number = 0; private xComponentController: XComponentController = new XComponentController(); setTimeInstance: number = 1; currentSurfaceID: string = ''; @@ -37,7 +35,6 @@ export default struct SampleUnitAVPlayView { build() { Stack({ alignContent: Alignment.Bottom }) { XComponent({ - id: '', type: XComponentType.SURFACE, controller: this.xComponentController }) @@ -45,7 +42,7 @@ export default struct SampleUnitAVPlayView { .backgroundImageSize({ width: Constants.FULL_SIZE, height: Constants.FULL_SIZE }) .onLoad(() => { this.xComponentController.setXComponentSurfaceRect({ - surfaceWidth: SURFACE_SIZE, surfaceHeight: SURFACE_SIZE + surfaceWidth: SURFACE_WIDTH, surfaceHeight: SURFACE_HEIGHT }) this.avPlayer.surfaceID = this.xComponentController.getXComponentSurfaceId(); }) @@ -72,34 +69,6 @@ export default struct SampleUnitAVPlayView { }) .height(this.xComponentHeight) .width(this.xComponentWidth) - - Slider({ value: this.curTime, min: 0, max: 100 }) - .enabled(false) - .height(4) - .width(320) - .trackThickness(3) - .blockColor(Color.Red) - .blockSize({ width: 4, height: 4 }) - .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => { - if (isVisible) { - animateTo({ - duration: DURATION, - iterations: -1, - expectedFrameRateRange: { - expected: 30, - min: 0, - max: 120, - }, - }, () => { - if (this.curTime >= 100) { - this.curTime = 0; - } - for (let i = 0; i < 101; i++) { - this.curTime += 1; - } - }) - } - }) } } } \ No newline at end of file diff --git a/entry/src/main/ets/view/SampleUnitPicView.ets b/entry/src/main/ets/view/SampleUnitPicView.ets index d20e4d74b5bfd630335eefa2a13cdcefa3e2fc01..406e67bab27da693f21eb66569517f1623e1961a 100644 --- a/entry/src/main/ets/view/SampleUnitPicView.ets +++ b/entry/src/main/ets/view/SampleUnitPicView.ets @@ -13,13 +13,134 @@ * limitations under the License. */ -import { MultiGrid } from './MultiGrid'; +import { Constants } from '../common/Constants'; +import { BreakpointType } from '../common/Utils'; + +interface GridConfig { + rows: number, + columns: number, + imageWidth: string +} + +const GRID_GAP: number = 4; +const IMAGE_SET_SIZE_9: number = 9; @Component export default struct SampleUnitPicView { - @Prop imageArray: Resource[]; + @StorageLink('currentBreakpoint') curBp: string = Constants.BREAK_POINT_SM; + private imageArray: (string | Resource)[] = []; + private arraySize: number = 0; + + aboutToAppear(): void { + this.arraySize = Math.min(this.imageArray.length, IMAGE_SET_SIZE_9); + } build() { - MultiGrid({ imageSource: this.imageArray }); + Column() { + Grid() { + ForEach(this.imageArray.slice(0, this.arraySize), (item: string | Resource, index: number) => { + GridItem() { + Image(item) + .objectFit(ImageFit.Cover) + .width(new BreakpointType(this.getSmConfig(), this.getMdConfig(), this.getLgConfig()).getValue(this.curBp) + .imageWidth) + .aspectRatio(1) + } + }, (index: number) => index.toString()) + } + .maxCount(new BreakpointType(this.getSmConfig(), this.getMdConfig(), this.getLgConfig()).getValue(this.curBp) + .columns) + .columnsGap(GRID_GAP) + .rowsGap(GRID_GAP) + .width(Constants.FULL_SIZE) + } + } + + private getSmConfig(): GridConfig { + let rows: number; + let columns: number; + if (this.arraySize <= 1) { + rows = 1; + columns = 1; + return { rows, columns, imageWidth: '60%' }; + } else if (this.arraySize === 2) { + rows = 1; + columns = 2; + } else if (this.arraySize === 3) { + rows = 1; + columns = 3; + } else if (this.arraySize === 4) { + rows = 2; + columns = 2; + } else if (this.arraySize <= 6) { + rows = 2; + columns = 3; + } else { + rows = 3; + columns = 3; + } + const imageWidth = `calc((100% - ${GRID_GAP * (columns - 1)}vp) / ${columns})`; + return { rows, columns, imageWidth }; + } + + private getMdConfig(): GridConfig { + let rows: number; + let columns: number; + if (this.arraySize <= 1) { + rows = 1; + columns = 1; + return { rows, columns, imageWidth: '40%' }; + } else if (this.arraySize === 2) { + rows = 1; + columns = 2; + } else if (this.arraySize === 3) { + rows = 1; + columns = 3; + } else if (this.arraySize === 4) { + rows = 2; + columns = 2; + return { rows, columns, imageWidth: '30%' }; + } else if (this.arraySize <= 6) { + rows = 2; + columns = 3; + } else if (this.arraySize <= 8) { + rows = 2; + columns = 4; + } else { + rows = 2; + columns = 5; + } + const imageWidth = `calc((100% - ${GRID_GAP * (columns - 1)}vp) / ${columns})`; + return { rows, columns, imageWidth }; + } + + private getLgConfig(): GridConfig { + let rows: number; + let columns: number; + if (this.arraySize <= 1) { + rows = 1; + columns = 1; + return { rows, columns, imageWidth: '40%' }; + } else if (this.arraySize === 2) { + rows = 1; + columns = 2; + } else if (this.arraySize === 3) { + rows = 1; + columns = 3; + } else if (this.arraySize === 4) { + rows = 1; + columns = 4; + } else if (this.arraySize <= 6) { + rows = 2; + columns = 3; + } else if (this.arraySize <= 8) { + rows = 2; + columns = 4; + } else { + rows = 2; + columns = 5; + } + const imageWidth = `calc((100% - ${GRID_GAP * (columns - 1)}vp) / ${columns})`; + return { rows, columns, imageWidth }; } } \ No newline at end of file diff --git a/entry/src/main/ets/view/SampleUnitVideoSecondView.ets b/entry/src/main/ets/view/SampleUnitVideoSecondView.ets deleted file mode 100644 index 0774096f04577a2da894d99e33c9e2bbce9ce285..0000000000000000000000000000000000000000 --- a/entry/src/main/ets/view/SampleUnitVideoSecondView.ets +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Constants } from '../common/Constants'; -import { BreakpointType } from '../common/Utils'; - -// Video name -const VIDEO_NAME = 'videoTest.mp4'; -// Set time delay -const DELAY = 1000; -// XComponent width -const X_COMPONENT_WIDTH: string = '70%'; -// XComponent height -const X_COMPONENT_HEIGHT: string = '50%'; -// Animation duration -const DURATION = 29024; - -@Component -export default struct SampleUnitVideoSecondView { - @State currentTime: number = 0; - @State xComponentWidth: string = X_COMPONENT_WIDTH; - @State xComponentHeight: string = X_COMPONENT_HEIGHT; - @State curTime: number = 0; - @StorageLink('currentBreakpoint') curBp: string = Constants.BREAK_POINT_SM; - controller: VideoController = new VideoController(); - durationTime: number = 0; - durationStringTime: string = '00:00'; - currentStringTime: string = '00:00'; - flag: boolean = false; - isLoading: boolean = false; - - build() { - Stack({ alignContent: Alignment.Bottom }) { - Video({ - src: $rawfile(VIDEO_NAME), - previewUri: $r('app.media.j'), - controller: this.controller - }) - .backgroundColor(Color.Transparent) - .width(new BreakpointType('100%', '70%', '60%').getValue(this.curBp)) - .height(new BreakpointType(200, 240, 320).getValue(this.curBp)) - .controls(false) - .autoPlay(false) - .objectFit(ImageFit.Cover) - .loop(false) - .onUpdate((event) => { - if (event) { - this.currentTime = event.time; - this.currentStringTime = this.changeSliderTime(this.currentTime); - } - }) - .onPrepared((event) => { - this.prepared(event?.duration); - }) - .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => { - if (isVisible) { - setTimeout(() => { - this.controller.start(); - }, DELAY) - } - if (!isVisible) { - this.controller.stop(); - } - }) - .onFinish(() => { - this.controller.start(); - }) - Slider({ value: this.curTime, min: 0, max: 100 }) - .enabled(false) - .height(4) - .width(320) - .trackThickness(3) - .blockColor(Color.Red) - .blockSize({ width: 4, height: 4 }) - .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => { - if (isVisible) { - animateTo({ - duration: DURATION, - iterations: -1, - expectedFrameRateRange: { - expected: 30, - min: 0, - max: 120, - }, - }, () => { - if (this.curTime >= 100) { - this.curTime = 0; - } - for (let i = 0; i < 101; i++) { - this.curTime += 1; - } - }) - } - }) - } - } - - prepared(duration: number) { - this.durationTime = duration; - let second: number = duration % 60; - let min: number = Number.parseInt((duration / 60).toString()); - let head = min < 10 ? `'0'${min}` : min; - let end = second < 10 ? `'0'${second}` : second; - this.durationStringTime = `${head}':'${end}`; - this.flag = true; - } - - changeSliderTime(value: number): string { - let second: number = value % 60; - let min: number = Number.parseInt((value / 60).toString()); - let head = min < 10 ? `'0'${min}` : min; - let end = second < 10 ? `'0'${second}` : second; - let nowTime = `${head}':'${end}`; - return nowTime; - } -} \ No newline at end of file diff --git a/entry/src/main/ets/view/SampleUnitVideoView.ets b/entry/src/main/ets/view/SampleUnitVideoView.ets index fa230e75e569a4a4f405edfa8558ae4938f41428..d5ebb09db4412b2cbdcf7c09850d72a044dba433 100644 --- a/entry/src/main/ets/view/SampleUnitVideoView.ets +++ b/entry/src/main/ets/view/SampleUnitVideoView.ets @@ -21,55 +21,89 @@ import { BreakpointType } from '../common/Utils'; const VIDEO_NAME = 'videoTest.mp4'; // Set time delay const DELAY = 1000; +// Animation duration +const DURATION = 29024; // Router url const ROUTER_URL = 'pages/NewPlayPage'; @Component export default struct SampleUnitVideoView { - @State currentTime: number = 0; + @State videoCurTime: number = 0; + @State sliderCurTime: number = 0; @StorageLink('currentBreakpoint') curBp: string = Constants.BREAK_POINT_SM; controller: VideoController = new VideoController(); durationTime: number = 0; durationStringTime: string = '00:00'; currentStringTime: string = '00:00'; flag: boolean = false; - isLoading: boolean = false; build() { - Video({ - src: $rawfile(VIDEO_NAME), - previewUri: $r('app.media.j'), - controller: this.controller - }) - .backgroundColor(Color.Transparent) - .width(new BreakpointType('100%', '70%', '60%').getValue(this.curBp)) - .height(new BreakpointType(200, 240, 320).getValue(this.curBp)) - .controls(false) - .autoPlay(false) - .objectFit(ImageFit.Cover) - .loop(false) - .onUpdate((event) => { - if (event) { - this.currentTime = event.time; - this.currentStringTime = this.changeSliderTime(this.currentTime); - } - }) - .onPrepared((event) => { - this.prepared(event?.duration); - }) - .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => { - if (isVisible) { - setTimeout(() => { - this.controller.start(); - }, DELAY) - } - if (!isVisible) { - this.controller.stop(); - } - }) - .onClick(() => { - router.pushUrl({ url: ROUTER_URL }); + Stack({ alignContent: Alignment.Bottom }) { + Video({ + src: $rawfile(VIDEO_NAME), + previewUri: $r('app.media.j'), + controller: this.controller }) + .backgroundColor(Color.Transparent) + .width(new BreakpointType('100%', '70%', '60%').getValue(this.curBp)) + .height(new BreakpointType(200, 240, 320).getValue(this.curBp)) + .controls(false) + .autoPlay(false) + .objectFit(ImageFit.Cover) + .loop(false) + .onUpdate((event) => { + if (event) { + this.videoCurTime = event.time; + this.currentStringTime = this.changeSliderTime(this.videoCurTime); + } + }) + .onPrepared((event) => { + this.prepared(event?.duration); + }) + .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean) => { + if (isVisible) { + setTimeout(() => { + this.controller.start(); + }, DELAY) + } + if (!isVisible) { + this.controller.stop(); + } + }) + .onFinish(() => { + this.controller.start(); + }) + .onClick(() => { + router.pushUrl({ url: ROUTER_URL }); + }) + Slider({ value: this.sliderCurTime, min: 0, max: 100 }) + .enabled(false) + .height(4) + .width(320) + .trackThickness(3) + .blockColor(Color.Red) + .blockSize({ width: 4, height: 4 }) + .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean) => { + if (isVisible) { + animateTo({ + duration: DURATION, + iterations: -1, + expectedFrameRateRange: { + expected: 30, + min: 0, + max: 120, + }, + }, () => { + if (this.sliderCurTime >= 100) { + this.sliderCurTime = 0; + } + for (let i = 0; i < 101; i++) { + this.sliderCurTime += 1; + } + }) + } + }) + } } prepared(duration: number) { diff --git a/entry/src/main/ets/view/SampleUnitView.ets b/entry/src/main/ets/view/SampleUnitView.ets index a9eec5b17cf7028ca8a2757a35f8a8a14d06d8f5..f2376dc2de0226c179490e13041c9061058b6155 100644 --- a/entry/src/main/ets/view/SampleUnitView.ets +++ b/entry/src/main/ets/view/SampleUnitView.ets @@ -15,11 +15,8 @@ import { Constants } from '../common/Constants'; import ButtonUnitItem from '../viewmodel/ButtonUnitItem'; -import TitleUnitItem from '../viewmodel/TitleUnitItem'; -import { AVPlayerItem } from './AVPlayerItem'; import ButtonItem from './ButtonItem'; import SampleUnitPicView from './SampleUnitPicView'; -import SampleUnitVideoSecondView from './SampleUnitVideoSecondView'; import SampleUnitVideoView from './SampleUnitVideoView'; import TitleAreaItem from './TitleAreaItem'; @@ -28,7 +25,7 @@ const FONT_FAMILY = 'HarmonyHeiTi'; // Margin about const STATIC_MARGIN = 8; // All types -const TYPE_ENUM = ['av', 'pic', 'video']; +const TYPE_ENUM = ['video', 'pic']; // Font weight. const FONT_WEIGHT = 400; // Border radius @@ -36,12 +33,10 @@ const BORDER_RADIUS = 5; @Component export default struct SampleUnitView { - @Prop areaUnit: TitleUnitItem; @Prop buttonUnit: ButtonUnitItem; @Prop type: string; @Prop imageArray: Resource[]; - controller: VideoController = new VideoController(); - avPlayer: AVPlayerItem = new AVPlayerItem(); + private controller: VideoController = new VideoController(); build() { Flex({ direction: FlexDirection.Column }) { @@ -53,11 +48,9 @@ export default struct SampleUnitView { .fontFamily(FONT_FAMILY) .margin({ bottom: STATIC_MARGIN }) if (this.type === TYPE_ENUM[0]) { - SampleUnitVideoSecondView({ controller: this.controller }); + SampleUnitVideoView({ controller: this.controller }); } else if (this.type === TYPE_ENUM[1]) { SampleUnitPicView({ imageArray: this.imageArray }); - } else if (this.type === TYPE_ENUM[2]) { - SampleUnitVideoView({ controller: this.controller }); } Column() { ButtonItem({ unit: this.buttonUnit }) diff --git a/entry/src/main/ets/viewmodel/BasicDataSource.ets b/entry/src/main/ets/viewmodel/BasicDataSource.ets index 8be4972efbabc8b8f82fd996fd4f0d9f1e39c10c..f4f2f744758c02226fb77635c04c4887d891e6f6 100644 --- a/entry/src/main/ets/viewmodel/BasicDataSource.ets +++ b/entry/src/main/ets/viewmodel/BasicDataSource.ets @@ -14,7 +14,6 @@ */ import { hilog } from '@kit.PerformanceAnalysisKit'; -import { AVPlayerItem } from '../view/AVPlayerItem'; import ButtonUnitItem from './ButtonUnitItem'; import SampleUnitItem from './SampleUnitItem'; @@ -26,10 +25,6 @@ export class DataSource { getData(): BasicDataSource { return this.dataSource; } - - clear() { - this.dataSource.data = []; - } } class BasicDataSource implements IDataSource { @@ -49,16 +44,12 @@ class BasicDataSource implements IDataSource { let buttonUnit: ButtonUnitItem = new ButtonUnitItem($r('sys.symbol.heart'), $r('sys.symbol.ellipsis_bubble'), $r('sys.symbol.star'), $r('sys.symbol.share')); - this.data = [new SampleUnitItem('video', buttonUnit, this.imageArray1, new VideoController(), new AVPlayerItem()), - new SampleUnitItem('pic', buttonUnit, this.imageArray3, new VideoController(), new AVPlayerItem()), - new SampleUnitItem('pic', buttonUnit, this.imageArray4, new VideoController(), new AVPlayerItem()), - new SampleUnitItem('pic', buttonUnit, this.imageArray8, new VideoController(), new AVPlayerItem()), - new SampleUnitItem('pic', buttonUnit, this.imageArray9, new VideoController(), new AVPlayerItem()), - new SampleUnitItem('pic', buttonUnit, this.imageArray3, new VideoController(), new AVPlayerItem()), - new SampleUnitItem('av', buttonUnit, this.imageArray1, new VideoController(), new AVPlayerItem()), - new SampleUnitItem('pic', buttonUnit, this.imageArray1, new VideoController(), new AVPlayerItem()), - new SampleUnitItem('pic', buttonUnit, this.imageArray3, new VideoController(), new AVPlayerItem()), - ]; + this.data = [new SampleUnitItem('video', buttonUnit, this.imageArray1), + new SampleUnitItem('pic', buttonUnit, this.imageArray3), new SampleUnitItem('pic', buttonUnit, this.imageArray4), + new SampleUnitItem('pic', buttonUnit, this.imageArray8), new SampleUnitItem('pic', buttonUnit, this.imageArray9), + new SampleUnitItem('pic', buttonUnit, this.imageArray3), new SampleUnitItem('video', buttonUnit, this.imageArray1), + new SampleUnitItem('pic', buttonUnit, this.imageArray1), + new SampleUnitItem('pic', buttonUnit, this.imageArray3),]; } totalCount(): number { diff --git a/entry/src/main/ets/viewmodel/SampleUnitItem.ets b/entry/src/main/ets/viewmodel/SampleUnitItem.ets index cceb7f34c60ca51052b49491d48064f4d0c5ed2a..88eea897056e836a58a965bf529e30a80c225750 100644 --- a/entry/src/main/ets/viewmodel/SampleUnitItem.ets +++ b/entry/src/main/ets/viewmodel/SampleUnitItem.ets @@ -13,22 +13,17 @@ * limitations under the License. */ -import { AVPlayerItem } from '../view/AVPlayerItem'; import ButtonUnitItem from './ButtonUnitItem'; export default class SampleUnitItem { public type: string; public button: ButtonUnitItem; public pic?: Resource[]; - public controller?: VideoController; - public avPlayer?: AVPlayerItem; constructor(type: string, button: ButtonUnitItem, pic: Resource[], - controller: VideoController, avPlayer: AVPlayerItem) { + ) { this.type = type; this.button = button; this.pic = pic; - this.controller = controller; - this.avPlayer = avPlayer; } } \ No newline at end of file