如何在UICollectionView中使用AVPlayer播放带原生控件的视频
问题解答
可以直接在UICollectionView中嵌入系统原生播放控件,不需要自定义播放按钮。你当前出现自动全屏的问题来自两个核心原因:
- 初始实现用的
AVPlayerLayer仅负责视频渲染,本身不包含任何播放控制UI - 尝试添加
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
相关产品推荐
相关产品推荐

