You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中Scroll View内视频播放器的自适应尺寸问题

解决ScrollView中SwiftUI视频播放器缩放异常问题

核心问题分析

AVPlayerViewController作为UIKit视图嵌入SwiftUI时,在ScrollView这类滚动容器内会丢失布局约束,加上原代码中硬编码的宽度计算和未明确的比例约束,导致尺寸缩放异常。以下是针对性的修复方案:

修复步骤及代码修改

1. 给视频播放器添加比例约束

在HustleVideoPlayer中,需要明确视频的宽高比,让SwiftUI能正确计算布局尺寸。支持固定比例(如16:9)或动态获取视频原始比例两种方式。

修改后的HustleVideoPlayer:

struct HustleVideoPlayer: View {
    let url: URL
    @State var player = AVPlayer()
    @State private var videoAspectRatio: CGFloat = 16/9 // 默认16:9,可替换为动态获取
    
    var body: some View {
        ZStack {
            VideoPlayer(player: $player)
        }
        .aspectRatio(videoAspectRatio, contentMode: .fit)
        .onAppear {
            // 初始化播放器
            player = AVPlayer(url: url)
            player.play()
            
            // 可选:动态获取视频原始宽高比
            let asset = AVAsset(url: url)
            let videoTracks = asset.tracks(withMediaType: .video)
            if let track = videoTracks.first {
                let naturalSize = track.naturalSize.applying(track.preferredTransform)
                videoAspectRatio = abs(naturalSize.width / naturalSize.height)
            }
        }
    }
}

2. 调整ScrollView内的HStack布局

去掉硬编码的宽度计算,让播放器自动填充可用水平空间,同时给其他元素设置明确尺寸保证布局稳定:

修改后的UploadHustleCamera:

struct UploadHustleCamera: View {
    let url: URL
    var body: some View {
        ScrollView {
            HStack(spacing: 12) {
                RoundedRectangle(cornerRadius: 5)
                    .frame(width: 40, height: 40)
                    .foregroundColor(.gray)
                
                Text("hello")
                
                Spacer()
                
                HustleVideoPlayer(url: url)
                    .frame(maxWidth: .infinity) // 占满剩余水平空间
            }
            .padding()
        }
    }
}

3. 统一视频填充模式避免冲突

确保VideoPlayer中的videoGravity和SwiftUI的contentMode匹配,防止布局逻辑冲突:

修改后的VideoPlayer:

struct VideoPlayer : UIViewControllerRepresentable {
    @Binding var player : AVPlayer
    
    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        controller.player = player
        controller.showsPlaybackControls = false
        // 和SwiftUI的contentMode: .fit对应,若用.fill则改为.resizeAspectFill
        controller.videoGravity = .resizeAspect
        return controller
    }
    
    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) { }
}

关键说明

  • ScrollView内的布局需要明确约束优先级,frame(maxWidth: .infinity)可让播放器自动填充剩余空间。
  • AVPlayerViewController本身不会自动适配SwiftUI布局,必须通过aspectRatio给它明确的宽高比约束。
  • 动态获取视频比例能让播放器贴合视频原始尺寸,固定比例场景可直接写死数值简化逻辑。

内容的提问来源于stack exchange,提问作者Ahmed Zaidan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:45:32