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

如何在UICollectionView中使用AVPlayer播放带原生控件的视频

问题解答

可以直接在UICollectionView中嵌入系统原生播放控件,不需要自定义播放按钮。你当前出现自动全屏的问题来自两个核心原因:

  1. 初始实现用的AVPlayerLayer仅负责视频渲染,本身不包含任何播放控制UI
  2. 尝试添加AVPlayerViewController时没有禁用自动全屏属性,也没有把控制器正确关联到cell的层级上

修改方案

1. 改造VideoCollectionViewCell

import UIKit
import AVFoundation
import AVKit
class VideoCollectionViewCell: UICollectionViewCell {
    static let identifier = "VideoCollectionViewCell"
    // 持有AVPlayerViewController防止被提前释放
    var avPlayerVC: AVPlayerViewController?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        contentView.clipsToBounds = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 配置方法新增父控制器参数,用于关联子控制器层级
    public func configureVideo(videoURL: String, parentVC: UIViewController) {
        // 先清理旧播放器,避免cell复用出现重叠、串音问题
        avPlayerVC?.view.removeFromSuperview()
        avPlayerVC?.removeFromParent()
        
        let player = AVPlayer(url: URL(string: videoURL)!)
        let playerVC = AVPlayerViewController()
        playerVC.player = player
        // 显式开启原生控件显示(默认值为true,此处明确标注作用)
        playerVC.showsPlaybackControls = true
        // 禁止播放时自动跳转全屏,是解决你自动全屏问题的核心配置
        playerVC.entersFullScreenWhenPlaybackBegins = false
        // 禁止播放结束自动退出全屏
        playerVC.exitsFullScreenWhenPlaybackEnds = false
        // 适配cell尺寸变化
        playerVC.view.frame = contentView.bounds
        playerVC.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        
        // 正确关联子控制器层级
        parentVC.addChild(playerVC)
        contentView.addSubview(playerVC.view)
        playerVC.didMove(toParent: parentVC)
        
        self.avPlayerVC = playerVC
        
        // 按需设置音量、自动播放逻辑
        player.volume = 0
        player.play()
    }
    
    // cell复用时主动释放资源
    override func prepareForReuse() {
        super.prepareForReuse()
        avPlayerVC?.player?.pause()
        avPlayerVC?.view.removeFromSuperview()
        avPlayerVC?.removeFromParent()
        avPlayerVC = nil
    }
}

2. 改造主控制器cellForItem调用逻辑

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let model = questions[indexPath.row]
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: VideoCollectionViewCell.identifier, for: indexPath) as! VideoCollectionViewCell
    // 传入当前控制器作为父控制器
    cell.configureVideo(videoURL: model, parentVC: self)
    cell.backgroundColor = .blue
    return cell
}

注意事项

  • 如果需要兼容iOS14以下系统,只需实现AVPlayerViewControllerDelegate的相关代理方法,拦截自动全屏逻辑即可
  • 建议仅保持当前屏幕中心可见的cell处于播放状态,避免同时播放多个视频导致内存占用过高、卡顿
  • 可监听collectionView滚动事件,在滚动停止时切换当前播放的cell,滚动过程中暂停所有视频提升流畅度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:45:03