关于使用Video组件实现在列表List组件中滑动到可见区域自动播放视频的问题

使用Video组件实现在列表List组件中滑动到可见区域自动播放视频的问题,实现代码如下:

if(this.centerIndex == this.currentIndex){  
  Video({  
    src: this.newsListData.videoUrl,  
    previewUri: this.newsListData.coverImg,  
  })  
    .autoPlay(true)  
    .loop(true)  
    .controls(false)  
    .objectFit(ImageFit.Contain)  
    .width(this.deviceWidth - 32)  
    .height(this.deviceWidth * 9 / 16)  
    .borderRadius(4)  
}else{  
  Image(this.newsListData.coverImg)  
    .width(this.deviceWidth - 32)  
    .height(this.deviceWidth * 9 / 16)  
    .objectFit(ImageFit.Contain)  
    .borderRadius(4)  
  Image($r('app.media.detail_video_icon'))  
    .width(40)  
    .height(40)  
}

监测滚动的index和Video组件所在的index对比,如果index相等,则使用Video组件播放视频,如果index不相等则用Image组件替换Video组件,但遇到问题就是列表滑动会卡顿,请问关于这个问题有更优化的解决思路吗?

HarmonyOS
2024-09-23 14:15:12
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
FengTianYa

1、如果list数据量过大,建议使用LazyForEach解决,参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-rendering-control-lazyforeach-V5

2、如果加载网络视频资源较慢造成卡顿,请检查网络,并且建议 预解码或者预加载视频

可以参考以下demo:

import { TreeSet } from '@kit.ArkTS'  
  
@Observed  
class ClassA {  
  public item: string = ""  
  public status: number = 0;  
  
  constructor(item: string, status: number) {  
    this.item = item;  
    this.status = status;  
  }  
}  
  
  
@Entry  
@Component  
struct Index {  
  @State feedList: ClassA[] = []  
  visibleItems: TreeSet<Number> = new TreeSet()  
  scroller: ListScroller = new ListScroller()  
  
  aboutToAppear(): void {  
    for (let i = 0; i < 10; i++) {  
      this.feedList.push(new ClassA("" + i, 0))  
    }  
  }  
  
  stopPlayWithOutTop() {  
    this.visibleItems.forEach((value: number) => {  
      if (this.visibleItems.getFirstValue() !== value && this.feedList[value].status == 1) {  
        this.feedList[value].status = 0  
      }  
    })  
  }  
  
  startPlayTop() {  
    this.feedList[Number(this.visibleItems.getFirstValue())].status = 1  
  }  
  
  play() {  
    this.stopPlayWithOutTop()  
    this.startPlayTop()  
  }  
  @Builder  
  private getListView() {  
    List({ scroller: this.scroller }) {  
      ForEach(this.feedList, (item: ClassA, index: number) => {  
        ListItem() {  
          CardPool(item, index)  
        }.onVisibleAreaChange([0, 0.5, 1], (isVisible: boolean, current: number) => {  
          if (isVisible && current > 0.5 && index != 1 && index != 2) {  
            this.visibleItems.add(index)  
            this.play()  
            console.log("xxx:", index, "显示触发", "正在播放:", this.visibleItems.getFirstValue(), "当前set数据量:", this.visibleItems.length)  
          } else if (!isVisible && current <= 0.5 && this.visibleItems.has(index)) {  
            this.feedList[index].status = 0  
            this.visibleItems.remove(index)  
            this.play()  
            console.log("xxx:", index, "隐藏触发", "正在播放:", this.visibleItems.getFirstValue(), "当前set数据量:", this.visibleItems.length)  
          }  
        })  
      })  
    }  
    .onScrollIndex((start: number, end: number, center: number) => {  
      console.log(`-----start:${start},end: ${end},center: ${center}`)  
    })  
    .divider({ strokeWidth: 1, color: 0x222222 })  
    .edgeEffect(EdgeEffect.None)  
  }  
  
  build() {  
    Column() {  
      this.getListView()  
    }.width("100%").height("100%")  
  }  
}  
@Builder  
function CardPool(item: ClassA, index: number) {  
  if (index == 0 || index == 5 || index == 6) {  
    card1(`第 ${index} 条`, item)  
  } else if (index == 4 || index == 8) {  
    card3(`第 ${index} 条`, item)  
  } else if (index == 3) {  
    card4(`第 ${index} 条`, item)  
  } else {  
    card2(`第 ${index} 条`)  
  }  
}  
  
@Builder  
function card1(item: string, playState: ClassA) {  
  Column({ space: 10 }) {  
    Text(item).width('100%')  
    Stack() {  
      VideoView({ videoId: item, videoHeight: 200, playState: playState })  
    }.width('100%')  
  }.padding(15)  
}  
  
@Builder  
function card2(item: string) {  
  Column({ space: 10 }) {  
    Text(item).width('100%')  
    Text('测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试')  
      .width('100%')  
  }.padding(15)  
}  
  
@Builder  
function card3(item: string, playState: ClassA) {  
  Column({ space: 10 }) {  
    Text(item).width('100%')  
    Stack() {  
      VideoView({ videoId: item, videoHeight: 300, playState: playState })  
    }.width(200)  
  }.padding(15).alignItems(HorizontalAlign.Start)  
}  
  
@Builder  
function card4(item: string, playState: ClassA) {  
  List() {  
    ListItem() {  
      card1(`${item} -- 1`, playState)  
    }  
  
    ListItem() {  
      card2(`${item} -- 2`)  
    }  
  }  
}  
@Component  
struct VideoView {  
  videoId: string = ''  
  videoHeight: number = 0  
  @State videoColor: ResourceColor = Color.Red  
  @ObjectLink @Watch("playStateWatch") playState: ClassA  
  
  playStateWatch() {  
    console.log("xxx:" + this.playState)  
    if (this.playState) {  
      VideoHelper.getInstance().registerPlayIndex(this.videoId)  
    } else {  
      VideoHelper.getInstance().unregisterPlayIndex(this.videoId)  
    }  
  }  
  
  build() {  
    Stack() {  
  
    }  
    .width('100%')  
    .height(this.videoHeight)  
    .borderRadius(8)  
    .backgroundColor(this.playState.status == 1 ? Color.Red : Color.Green)  
  }  
}  
  
class VideoHelper {  
  playingId: string = ''  
  private static INSTANCE: VideoHelper = new VideoHelper();  
  
  public static getInstance(): VideoHelper {  
    if (VideoHelper.INSTANCE == null) {  
      VideoHelper.INSTANCE = new VideoHelper();  
    }  
    return VideoHelper.INSTANCE;  
  }  
  
  registerPlayIndex(id: string): boolean {  
    if (this.playingId && this.playingId !== id) {  
      return false  
    }  
  
    this.playingId = id  
    return true  
  }  
  
  unregisterPlayIndex(id: string) {  
    if (this.playingId === id) {  
      this.playingId = ''  
    }  
  }  
}  
if (isVisible && current > 0.5 && index != 1 && index != 2) {  
//这里的index!=1&&index!=2的条件是模拟数据中不存在视频的情况
分享
微博
QQ
微信
回复
2024-09-23 18:29:28
相关问题