iOS16添加翻转图层后AVPlayer播放按钮不显示问题求解
AVPlayer视频翻转导致控制按钮不显示问题修复
问题现象
- 应用内使用AVPlayer播放单份本地mp4视频,不同业务场景需要对同一份视频做水平翻转
- iOS16系统下异常:播放/暂停、15秒快进/快退等控制按钮功能完全正常,可以正常点击触发,但按钮完全不显示,对应示意图第4项效果
- 原有实现逻辑是在弹出AVPlayerViewController后,手动新建一个做了翻转变换的AVPlayerLayer盖在控制器视图上,这个额外添加的图层直接遮挡了iOS16新布局下的播放控制层。

原有问题代码
@IBAction func pressButton(_ sender: Any) { guard let path = Bundle.main.path(forResource: "sample-5s", ofType:"mp4") else { return } let avPlayer = AVPlayer(url: URL(fileURLWithPath: path)) let avPlayerController = AVPlayerViewController() present(avPlayerController, animated: true, completion: { // 问题根源:额外新增AVPlayerLayer盖在控制器最上层,遮挡控制UI let flippedLayer = AVPlayerLayer(player: avPlayer) let transform = CGAffineTransform(scaleX: -1.0, y: 1.0) flippedLayer.frame = (avPlayerController as UIViewController).view.frame flippedLayer.setAffineTransform(transform) (avPlayerController as UIViewController).view.layer.addSublayer(flippedLayer) avPlayerController.player = avPlayer avPlayer.play() }) }
最优修复方案
不要手动新增AVPlayerLayer覆盖在AVPlayerViewController视图上,直接将翻转逻辑作用在视频渲染本身,完全不触碰系统控制层,兼容iOS15、iOS16及以上所有系统版本,也不需要强制切回iOS15的旧布局。
方案1:通过AVVideoComposition实现视频翻转(推荐)
翻转逻辑直接作用在视频资源的渲染流程中,不会对系统控制UI产生任何遮挡,性能最优,是官方推荐的视频变换实现方式:
@IBAction func pressButton(_ sender: Any) { guard let path = Bundle.main.path(forResource: "sample-5s", ofType:"mp4") else { return } let videoURL = URL(fileURLWithPath: path) let asset = AVAsset(url: videoURL) guard let videoTrack = asset.tracks(withMediaType: .video).first else { return } let playerItem = AVPlayerItem(asset: asset) // 配置水平翻转的视频合成规则 let videoComposition = AVMutableVideoComposition(asset: asset, applyingCIFiltersWithHandler: { request in let source = request.sourceImage // 水平翻转:x轴缩放-1后平移对应宽度,适配CoreImage坐标系 let flippedTransform = CGAffineTransform(scaleX: -1, y: 1).translatedBy(x: -source.extent.width, y: 0) let flippedImage = source.transformed(by: flippedTransform) request.finish(with: flippedImage, context: nil) }) videoComposition.renderSize = videoTrack.naturalSize playerItem.videoComposition = videoComposition let avPlayer = AVPlayer(playerItem: playerItem) let avPlayerController = AVPlayerViewController() avPlayerController.player = avPlayer present(avPlayerController, animated: true) { avPlayer.play() } }
关于保留iOS15播放布局的说明
iOS16对AVPlayerViewController的控制层UI做了系统级迭代,苹果没有提供任何公开API可以强制切换回iOS15的旧控制布局。不要尝试通过遍历子视图修改层级、hook系统方法的方式强行修改控制层样式,这类操作极容易在后续系统版本出现兼容崩溃,也有概率在App Store审核时被拒。
注意事项
- 不要手动给AVPlayerViewController新增AVPlayerLayer,控制器内部会自动创建视频渲染图层,额外添加的图层不仅会遮挡UI,还会造成双倍的视频渲染性能损耗
- 所有视频本身的变换(翻转、旋转、裁剪、加滤镜)优先通过AVVideoComposition实现,稳定性和兼容性远高于手动调整图层
- 不要随意修改AVPlayerViewController的内部子视图层级,苹果会在不同系统版本调整内部视图结构,手动修改层级的适配成本极高
内容的提问来源于stack exchange,提问作者Luciano Perez
相关产品推荐
相关产品推荐

