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

如何在iOS应用内直接启动画中画(Picture-in-Picture)功能?

在应用内指定视图出现时启动画中画功能

当然可以实现,核心是把画中画相关实例(AVPlayer、AVPlayerViewController、AVPictureInPictureController)作为视图控制器的属性持有,在指定视图的生命周期方法(比如viewDidAppear)中完成初始化、播放启动和画中画触发,同时确保满足画中画的启动条件。

关键修改点

  • 将播放器、播放器控制器、画中画控制器声明为视图控制器属性,避免局部变量被提前释放
  • 在目标视图的viewDidAppear中执行初始化逻辑,确保视图已加载完成
  • 提前检查设备是否支持画中画功能,避免无效调用
  • 保留你已在AppDelegate中配置的音频会话设置

修改后的代码示例

class TargetViewController: UIViewController {
    // 声明为属性持有,防止被提前释放
    private var player: AVPlayer?
    private var avPlayerController: AVPlayerViewController?
    private var pipController: AVPictureInPictureController?
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // 视图出现时启动视频和画中画
        setupAndLaunchPIP()
    }
    
    private func setupAndLaunchPIP() {
        // 检查设备是否支持画中画
        guard AVPictureInPictureController.isPictureInPictureSupported() else {
            print("当前设备不支持画中画功能")
            return
        }
        
        guard let videoURL = Bundle.main.url(forResource: "video", withExtension: "mp4") else {
            print("未找到目标视频文件")
            return
        }
        
        // 初始化播放器与控制器
        player = AVPlayer(url: videoURL)
        avPlayerController = AVPlayerViewController()
        avPlayerController?.player = player
        avPlayerController?.canStartPictureInPictureAutomaticallyFromInline = true
        
        // 可选:如果不需要显示完整播放器界面,可隐藏控制器视图
        if let playerView = avPlayerController?.view {
            playerView.frame = .zero
            playerView.isHidden = true
            view.addSubview(playerView)
        } else {
            // 或直接present播放器控制器,根据需求选择
            present(avPlayerController!, animated: true)
        }
        
        // 启动视频播放
        player?.play()
        
        // 初始化并启动画中画
        guard let player = player else { return }
        let playerLayer = AVPlayerLayer(player: player)
        pipController = AVPictureInPictureController(playerLayer: playerLayer)
        pipController?.canStartPictureInPictureAutomaticallyFromInline = true
        pipController?.delegate = self // 可选:设置代理处理画中画状态变化
        
        pipController?.startPictureInPicture()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // 视图消失时清理资源,避免内存泄漏
        player?.pause()
        pipController?.stopPictureInPicture()
        pipController = nil
        player = nil
        avPlayerController?.dismiss(animated: false)
        avPlayerController = nil
    }
}

// 可选:实现画中画代理方法,处理状态回调
extension TargetViewController: AVPictureInPictureControllerDelegate {
    func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
        print("画中画已启动")
    }
    
    func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
        print("画中画已停止")
    }
}

注意事项

  • 若不需要显示完整播放器界面,可将AVPlayerViewController的视图添加到当前视图并隐藏,避免启动画中画时弹出播放器窗口
  • 必须确保在调用startPictureInPicture()前,播放器已经开始播放(即player?.play()已执行),否则可能启动失败
  • 部分iOS版本可能要求画中画启动关联用户交互,但在viewDidAppear中触发属于合法场景,建议测试不同系统版本的表现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:05:09