TabView 用于在滚动上附加更多项目时出现卷轴问题

问题描述 投票:0回答:1

我正在我的应用程序上使用包含各个

TabView
AVPlayer
实现 Instagram Reels 样式视图。

当我尝试将其他元素添加到我的初始列表(以模拟无限滚动)时,我得到了一个非常奇怪的效果:正如您在视频中看到的,当播放 id 98 的卷轴时,我将新卷轴添加到我的列表中并且当前播放的视频出现“闪烁”,无论上一个视频的音频是否开始。

看起来

TabView
已重新渲染,但不正确。

这是我的代码:

卷轴视图:

GeometryReader { geo in
    TabView(selection: $currentReel) {
        ForEach(0..<items.count, id: \.self) { i in
            let reelModel = items[i]
            ReelPlayerView(reel: reelModel.reel, videoPlayerModel: reelModel.videoPlayerModel, width: geo.size.width, height: geo.size.height)
                .frame(width: geo.size.width)
                .rotationEffect(.init(degrees: 270))
                .ignoresSafeArea(.all, edges: .top)
                .tag(i)
                .id(i)
        }
    }
    .id(items.count)
    .rotationEffect(.init(degrees: 90))
    .frame(width: geo.size.height)
    .tabViewStyle(.page(indexDisplayMode: .never))
    .indexViewStyle(.page(backgroundDisplayMode: .never))
    .frame(maxWidth: geo.size.width)
    .onChange(of: currentReel) { value in
        for i in items.indices {
            if i == value {
                items[i].videoPlayerModel.play()
            } else {
                items[i].videoPlayerModel.stop()
            }
        }
        
        if (currentReel == Int(items.count - 1)) {
            self.items.append(contentsOf: self.items) --> here I append the new items, when I'm at the half of scrolled items
        }
    }
    .onAppear() {
        if items[currentReel].videoPlayerModel.player != nil {
            items[currentReel].videoPlayerModel.play()
        }
    }
    .onDisappear() {
        items[currentReel].videoPlayerModel.pause()
    }
}
.ignoresSafeArea(.all, edges: .top)

ReelPlayer视图:

CustomVideoPlayer(hls: reel.video_url!) { videoPlayer in
    DispatchQueue.main.async {
        videoPlayerModel.player = videoPlayer
    }
}
.frame(width: width, height: height)

如何解决?

swiftui avplayer swiftui-tabview
1个回答
0
投票

尝试删除

.id(items.count)
,因为这会导致
TabView
在更新
items
时重新渲染。

无关:

currentReel
更改时,您无需循环遍历整个项目。只需开始播放当前项目,并停止上一个项目:

.onChange(of: currentReel) { newValue in
    if newValue > 0 {
        items[newValue - 1].videoPlayerModel.stop()
    }
    items[newValue].videoPlayerModel.play()
    let lastItem = newValue == items.count - 1
    if lastItem {
        items.append(contentsOf: items)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.