HarmonyOS鸿蒙Next中如何实现Swiper组件嵌套Video组件每次切换swiper都自动重新播放视频
HarmonyOS鸿蒙Next中如何实现Swiper组件嵌套Video组件每次切换swiper都自动重新播放视频
import { Route } from "@hzw/zrouter";
import { RouterConstants } from "../common/utils/RouterConst";
@Route({ name: RouterConstants.HOME_PAGE })
@ComponentV2
export struct HomePage {
@Event onFullScreen():void => {};
controller: VideoController = new VideoController()
@Local demo1: Resource = $rawfile('demo1.mp4')
@Local demo2: Resource = $rawfile('demo2.mp4')
@Local demo3: Resource = $rawfile('demo3.mp4')
@Local demo4: Resource = $rawfile('demo4.mp4')
@Local isAutoPlay: boolean = true
@Local showControls: boolean = false
build() {
Column() {
Swiper() {
Video({
src: this.demo1,
controller: this.controller
})
.autoPlay(this.isAutoPlay)
.controls(this.showControls)
.width('100%')
.height('100%')
Video({
src: this.demo2,
controller: this.controller
})
.autoPlay(this.isAutoPlay)
.controls(this.showControls)
.width('100%')
.height('100%')
Video({
src: this.demo3,
controller: this.controller
})
.autoPlay(this.isAutoPlay)
.controls(this.showControls)
.width('100%')
.height('100%')
Video({
src: this.demo4,
controller: this.controller
})
.autoPlay(this.isAutoPlay)
.controls(this.showControls)
.width('100%')
.height('100%')
}
.loop(true)
.indicator(false) // 隐藏指示点
}
.width('100%')
.height('100%')
}
}
更多关于HarmonyOS鸿蒙Next中如何实现Swiper组件嵌套Video组件每次切换swiper都自动重新播放视频的实战教程也可以访问 https://www.itying.com/category-93-b0.html
【背景知识】
-
Video 组件视频播放后默认不会自动暂停,而是会继续播放,只有通过VideoController的pause方法可以暂停播放。另外还可以通过VideoController的stop方法控制视频重新播放。
-
Swiper 组件滑动时默认不会触发只有通过VideoController的pause或stop方法,但是Swiper滑动时会触发onChange事件。
【解决方案】
Swiper滑动时触发onChange事件,在onChange方法里调用VideoController的stop方法即可实现滑动过程控制视频重新播放,代码示例如下:
@Entry
@Component
struct Index {
private controllerList: VideoController[] =
[new VideoController(), new VideoController(), new VideoController(), new VideoController()]
@State swiperIndex: number = 0
build() {
Swiper() {
ForEach([0, 1, 2, 3], (item: number) => {
Column() {
Text('第' + (item + 1) + '个组件页')
.width('100%')
.backgroundColor(Color.Gray)
.textAlign(TextAlign.Center)
.fontSize(30)
Video({
src: 'https://www.example.com/example.mp4',
controller: this.controllerList[item]
})
.objectFit(ImageFit.Contain)
.controls(true)
.autoPlay(false)
.loop(true)
.height(200)
}
})
}
.loop(true)
.backgroundColor(Color.Black)
.onChange((index: number) => {
const preIndex = index > 0 ? index - 1 : 3
const nextIndex = index < 3 ? index + 1 : 0
this.controllerList[preIndex].stop()
this.controllerList[nextIndex].stop()
this.swiperIndex = index
})
}
}
【常见FAQ】
Q:如果要在Swiper切换时暂停播放,应该如何设置?
A:只需将上述样例代码中onChange方法里调用的stop()方法换成pause()即可。样例代码如下:
.onChange((index: number) => {
const preIndex = index > 0 ? index - 1 : 3
const nextIndex = index < 3 ? index + 1 : 0
this.controllerList[preIndex].pause()
this.controllerList[nextIndex].pause()
this.swiperIndex = index
})
更多关于HarmonyOS鸿蒙Next中如何实现Swiper组件嵌套Video组件每次切换swiper都自动重新播放视频的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
请问在首页放置 swiper 嵌套 video 沉浸式的首次加载会有个黑屏闪一下,已经设置了预览图还是不行,只有首次加载会这样,有什么好的解决方案吗
https://developer.huawei.com/consumer/cn/doc/architecture-guides/audio-v1_2-ts_7-0000002298352337 按照这两个方案设置了都不行,
我使用链接里的方案一,给Video对象设置了previewUri属性,能够显示预览图片。烦请在真机上再验证一下呢?
我的代码:
{
"src": "[https://www.example.com/example.mp4](https://www.example.com/example.mp4)",
"previewUri": "$r('app.media.app_icon')",
"controller": this.controllerList[item]
}
import { Route } from “@hzw/zrouter”; import { RouterConstants } from “…/common/utils/RouterConst”;
interface VideoItem { id: number; src: Resource; preview: Resource; controller: VideoController; }
@Route({ name: RouterConstants.HOME_PAGE }) @ComponentV2 export struct HomePage { @Event onFullScreen: () => void = () => {}; @Local isAutoPlay: boolean = true; @Local showControls: boolean = false;
// 当前索引 @Local currentIndex: number = 0;
// 保存上一个索引 @Local previousIndex: number = 0;
// 使用数组存储所有视频资源(每个视频有自己的控制器) private videoList: VideoItem[] = [ { id: 1, src: $rawfile(‘demo1.mp4’), preview: $rawfile(‘demo1_preview.png’), controller: new VideoController() }, { id: 2, src: $rawfile(‘demo2.mp4’), preview: $rawfile(‘demo2_preview.png’), controller: new VideoController() }, { id: 3, src: $rawfile(‘demo3.mp4’), preview: $rawfile(‘demo3_preview.png’), controller: new VideoController() }, { id: 4, src: $rawfile(‘demo4.mp4’), preview: $rawfile(‘demo4_preview.png’), controller: new VideoController() }, ];
build() {
Column() {
Swiper() {
ForEach(this.videoList, (item: VideoItem, index: number) => {
Video({
src: item.src,
previewUri: item.preview,
controller: item.controller
})
.autoPlay(index === 0 && this.isAutoPlay) // 只有首个视频自动播放
.controls(this.showControls)
.width(‘100%’)
.height(‘100%’)
.onStart(() => {
console.info(视频${item.id}开始播放
);
})
.onFinish(() => {
console.info(视频${item.id}播放完成
);
})
})
}
.loop(true)
.indicator(false)
.onChange((index: number) => {
console.info(切换到视频${index + 1}
);
// 记录上一个索引
this.previousIndex = this.currentIndex;
// 重置上一个视频
this.videoList[this.previousIndex].controller.pause();
// 更新当前索引
this.currentIndex = index;
// 获取当前视频的控制器
const currentController = this.videoList[index].controller;
currentController.start();
})
}
.width('100%')
.height('100%')
.gesture(
GestureGroup(GestureMode.Exclusive,
LongPressGesture()
.onAction(() => {
console.info('触发长按 - 但不执行点击操作');
}),
TapGesture({ count: 1 })
.onAction(() => {
if (this.onFullScreen) {
this.onFullScreen();
}
}),
PanGesture()
.onActionStart((event: GestureEvent) => {})
.onActionUpdate((event: GestureEvent) => {})
.onActionEnd(() => {})
)
)
}
// 组件销毁前停止所有视频 aboutToDisappear() { this.videoList.forEach((item) => { item.controller.stop(); }); } }
首次加载的时候会出现黑屏的情况,切换的时候也是这样,当全部展示一遍后就不会有黑屏问题了
期待HarmonyOS能在未来推出更多针对特定场景的优化功能。
因为绑定的controler都是同一个,所以状态都一样,isAutoPlay也是true的。
解决了改成了 每个视频一个控制器。但是还有个问题就是每次切换视频都会黑屏一下,并且设置了封面图。代码再二楼,麻烦大佬指点一下。
初次切换有黑屏是因为首次加载的黑屏,swiper有个缓存属性,可以试下,不过治标不治本。没想到啥好办法,
在HarmonyOS鸿蒙Next中,可以通过在Swiper组件的onChange
事件中调用Video组件的start
方法来实现每次切换Swiper时自动重新播放视频。具体实现如下:在Swiper的onChange
事件中获取当前Video组件的引用,并调用其start
方法。确保Video组件的autoplay
属性设置为false
,以避免自动播放干扰。这样,每次切换Swiper时,Video组件都会重新开始播放。
在HarmonyOS Next中实现Swiper嵌套Video组件时自动重新播放视频,可以通过监听Swiper的change事件来实现。以下是修改后的关键代码:
[@State](/user/State) currentIndex: number = 0
build() {
Column() {
Swiper({
index: this.currentIndex,
onChange: (index: number) => {
this.currentIndex = index
this.controller.stop()
this.controller.start()
}
}) {
// 原有Video组件代码保持不变
}
.loop(true)
.indicator(false)
}
}
主要修改点:
- 添加@State变量currentIndex来跟踪当前Swiper索引
- 在Swiper组件中添加onChange事件监听
- 当索引变化时,先停止当前视频再重新开始播放
这样每次切换Swiper时都会触发视频重新播放。注意所有Video组件共用了同一个controller,所以需要确保切换时正确控制播放状态。