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

10 回复

【背景知识】

  • Video 组件视频播放后默认不会自动暂停,而是会继续播放,只有通过VideoControllerpause方法可以暂停播放。另外还可以通过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)
  }
}

主要修改点:

  1. 添加@State变量currentIndex来跟踪当前Swiper索引
  2. 在Swiper组件中添加onChange事件监听
  3. 当索引变化时,先停止当前视频再重新开始播放

这样每次切换Swiper时都会触发视频重新播放。注意所有Video组件共用了同一个controller,所以需要确保切换时正确控制播放状态。

回到顶部