HarmonyOS 鸿蒙Next:父来控制进度条,swiper可左右滑动视频,滑动了进度条则重置为0重新渲染

发布于 1周前 作者 wuwangju 来自 鸿蒙OS

HarmonyOS 鸿蒙Next:父来控制进度条,swiper可左右滑动视频,滑动了进度条则重置为0重新渲染

import { TimeBigMediaComponent } from './video'
import { TimeBigMediaVM } from './vm'

// xxx.ets
@Component
struct VideoCreateComponent {
  timeBigMediaVM: TimeBigMediaVM = new TimeBigMediaVM()
  // 视频
  swiperVideoList: string[] = [
    'http://vjs.zencdn.net/v/oceans.mp4',
    'https://prod-streaming-video-msn-com.akamaized.net/ba258271-89c7-47bc-9742-bcae67c23202/f7ff4fe4-1346-47bb-9466-3f4662c1ac3a.mp4',
    'https://prod-streaming-video-msn-com.akamaized.net/bc3e9341-3243-4d2c-8469-940fef56ca2d/4720a02b-eabd-4593-a1d9-5c5d61916853.mp4',
    'https://prod-streaming-video-msn-com.akamaized.net/b701c37f-3464-4d0a-a165-4a9468080ebd/7afe0873-a1f4-4fad-b771-a917687fcfc6.mp4'
  ]

  build() {
    Stack({alignContent:Alignment.Bottom}) {
      Swiper() {
        this.builderVideo()
      }
      .onChange(() => {
        this.timeBigMediaVM.controller.reset()
      })
      .height('100%')
      .width('100%')
      this.builderSlider()
    }
  }

  @Builder
  builderVideo() {
    ForEach(this.swiperVideoList, (url: string) => {
      Row() {
        TimeBigMediaComponent({
          timeBigMediaVM: this.timeBigMediaVM,
          isVideo: true,
          resourceUrl: url
        })
      }
    })
  }

  // 自定义进度条
  @Builder
  builderSlider() {
    Row() {
      Row() {
        Image(this.timeBigMediaVM.isVideoPlaying ?
          'http://pic06.babytreeimg.com/knowledge/2024/1204/FiMmhAGAlKQTwhY78Wl3YuffJBdF' :
          'http://pic08.babytreeimg.com/knowledge/2024/1203/Flui7PYdzn7YlewzZiXYzQinoY5d')
          .width(this.timeBigMediaVM.handlePercentage(24))
          .margin({ right: 4 })
      }.onClick(() => { // 点击视频本体控制暂停播放
        this.timeBigMediaVM.isVideoPlaying = !this.timeBigMediaVM.isVideoPlaying
        this.timeBigMediaVM.isVideoPlaying == true ? this.timeBigMediaVM.controller.start() :
        this.timeBigMediaVM.controller.pause()
      })

      Text(this.timeBigMediaVM.currentVideoProgressTime)
        .lineHeight(20)
        .fontColor('#FFFFFF')
        .fontSize(14)
      Slider({
        value: this.timeBigMediaVM.currentVideoProgressInSecond,
        max: this.timeBigMediaVM.videoLengthInSecond,
        step: 1,
        style: SliderStyle.OutSet
      })
        .margin({ left: 10, right: 10 })
        .trackColor('rgba(255, 255, 255, 0.3)')
        .selectedColor('#FFFFFF')
        .blockSize({
          width: 10,
          height: 10
        })//设置滑块大小
        .width(this.timeBigMediaVM.handlePercentage(219))
        .onChange((value: number, mode: SliderChangeMode) => {
          this.timeBigMediaVM.currentVideoProgressInSecond = value
          this.timeBigMediaVM.controller.setCurrentTime(value, SeekMode.Accurate)
          this.timeBigMediaVM.currentVideoProgressTime = this.timeBigMediaVM.processSecondToTime(value)
        })
      Text(this.timeBigMediaVM.videoLengthTime)
        .lineHeight(20)
        .fontColor('#FFFFFF')
        .fontSize(14)
    }
    .height(48)
    .margin({ bottom: 34 + 48 })
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .margin({ bottom: 32 + 48 })
    .width('100%')
  }
}

import { TimeBigMediaVM } from "./vm"

//视频图片组件
@Component
export struct TimeBigMediaComponent {
  @Prop resourceUrl: string
  @Prop isVideo: boolean //是否是视频类型
  @Require timeBigMediaVM: TimeBigMediaVM = new TimeBigMediaVM()

  aboutToAppear(): void {
    this.isVideo = this.isVideo
  }

  build() {
    Stack() {
      if (this.isVideo) {
        this.builderVideo()
      } else {
        Image(this.resourceUrl)
          .objectFit(ImageFit.Contain)
      }

    }
    .height('100%')
    .width('100%');
  }

  @Builder
  builderVideo() {
    Stack({ alignContent: Alignment.BottomEnd }) {
      Video({
        src: this.resourceUrl,
        controller: this.timeBigMediaVM.controller
      })
        .muted(false)//设置是否静音
        .controls(false)//设置是否显示默认控制条
        .autoPlay(true)//设置是否自动播放
        .loop(true)//设置是否循环播放
        .objectFit(ImageFit.Contain)
        .onPrepared((e) => { // 视频加载完毕
          this.timeBigMediaVM.videoLengthInSecond = e.duration
          this.timeBigMediaVM.videoLengthTime = this.timeBigMediaVM.processSecondToTime(e.duration)
        })
        .onFinish(() => { // 播放结束的时候
          this.timeBigMediaVM.currentVideoProgressTime = '00.00'
        })
        .onUpdate((e) => { // 播放进度变化的时候
          this.timeBigMediaVM.currentVideoProgressInSecond = e.time // 用于把播放进度同步到自定义进度条的当前值中
          this.timeBigMediaVM.currentVideoProgressTime = this.timeBigMediaVM.processSecondToTime(e.time)
        })
    }
    .width('100%')
    .height('100%')
  }
}
@ObservedV2
export class TimeBigMediaVM{
  controller: VideoController = new VideoController() //视频控制器
  @Trace currentVideoProgressTime: string = '00.00'; //视频进度值
  @Trace videoLengthTime: string = '00:00' // 视频进度最大值
  @Trace currentVideoProgressInSecond: number = 0 // 视频当前滑块进度值
  @Trace videoLengthInSecond: number = 0 // 视频总长度滑块最大值
  @Trace isVideoPlaying: boolean = true // 控制是否播放
  @Trace isVideo: boolean=false //是否是视频类型
  //处理百分比
  handlePercentage(number: number): string {
    let result = (number / 375) * 100;
    return result + '%'; // 将计算结果拼接上%符号后返回字符串形式
  }

  // 处理数据为 mm:ss 格式
  processSecondToTime(seconds: number): string {
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = seconds % 60;
    return `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`;
  }
}
export class VideoPlayModel {
  public currentTime: number = 0;
  public currentStringTime: string = '00:00';
  public durationTime: number = 0;
  public durationStringTime: string = '00:00';
  public isPlay: boolean = false;
  public isOpacity: boolean = false;
  public flag: boolean = false;
  public isLoading: boolean = false;
  public progressVal: number = 0;
  public controller: VideoController = new VideoController();
}

更多关于HarmonyOS 鸿蒙Next:父来控制进度条,swiper可左右滑动视频,滑动了进度条则重置为0重新渲染的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

你看你的代码,共用一个控制器,swiper每次change的时候你都reset,那肯定是重置的

cke_861.png

更多关于HarmonyOS 鸿蒙Next:父来控制进度条,swiper可左右滑动视频,滑动了进度条则重置为0重新渲染的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS中,若要实现父组件控制进度条,同时swiper组件可左右滑动视频,并在滑动进度条时重置为0并重新渲染的功能,你可以采取以下策略:

  1. 父组件控制进度条

    • 使用状态管理(如DataAbility或全局状态)在父组件中存储进度条的值。
    • 通过@Binding@Env等注解将进度条值传递给子组件。
  2. swiper组件滑动视频

    • 利用swiper组件的滑动事件监听功能,结合视频播放器控件(如VideoPlayer)实现视频的左右滑动。
    • 确保swiper组件的滑动与视频播放器的当前播放位置同步。
  3. 进度条滑动重置与重新渲染

    • 在进度条组件上添加滑动事件监听器。
    • 当检测到滑动事件时,将进度条的值重置为0,并触发重新渲染swiper组件及其包含的视频内容。
    • 这可能需要重新加载视频或重置视频播放器的状态。

请注意,实现上述功能可能需要结合HarmonyOS的UI框架和组件库进行具体开发。如果问题依旧没法解决请联系官网客服,官网地址是: https://www.itying.com/category-93-b0.html

回到顶部