Swift iOS应用:监听画中画模式左右滑动以关闭相机的方法
监听画中画滑动最小化并关闭相机的解决方案
你遇到的问题核心在于:用户滑动PiP视图到屏幕边缘最小化的操作,并不会触发AVPictureInPictureControllerDelegate的终止类代理方法(比如pictureInPictureControllerDidStopPictureInPicture:),这类操作仅会改变PiP视图的位置。要检测该行为,需要结合通知监听和位置判断来实现。
以下是具体实现步骤:
1. 初始化PiP控制器并添加通知监听
在你的视频通话视图控制器中,初始化AVPictureInPictureController时,同时注册两个关键通知,覆盖位置变化和状态变化场景:
import AVKit class VideoCallVC: UIViewController, AVPictureInPictureControllerDelegate { private var pipController: AVPictureInPictureController? private var captureSession: AVCaptureSession? // 你的相机捕获会话实例 override func viewDidLoad() { super.viewDidLoad() // 假设你已完成用于PiP的AVPlayerLayer初始化 guard let playerLayer = yourVideoPlayerLayer else { return } pipController = AVPictureInPictureController(playerLayer: playerLayer) pipController?.delegate = self // 注册PiP位置变化通知 NotificationCenter.default.addObserver( self, selector: #selector(handlePiPFrameChange), name: AVPictureInPictureController.pictureInPictureFrameDidChangeNotification, object: pipController ) // 注册PiP状态变化通知 NotificationCenter.default.addObserver( self, selector: #selector(handlePiPStateChange), name: AVPictureInPictureController.pictureInPictureStateDidChangeNotification, object: pipController ) }
2. 检测PiP滑动到边缘的操作
在handlePiPFrameChange方法中,通过判断PiP视图的frame是否接近屏幕左右边缘,识别用户的最小化操作:
@objc private func handlePiPFrameChange(_ notification: Notification) { guard let pipController = notification.object as? AVPictureInPictureController else { return } let pipFrame = pipController.pictureInPictureFrame let screenBounds = UIScreen.main.bounds // 设置边缘检测阈值(可根据UI需求调整) let edgeThreshold: CGFloat = 20 let isNearLeftEdge = pipFrame.origin.x <= edgeThreshold let isNearRightEdge = pipFrame.origin.x + pipFrame.width >= screenBounds.width - edgeThreshold if isNearLeftEdge || isNearRightEdge { // 用户将PiP滑动至边缘,执行关闭相机操作 stopCamera() } }
3. 处理PiP主动关闭的情况
保留代理方法和状态变化通知,覆盖用户主动关闭PiP的场景:
@objc private func handlePiPStateChange(_ notification: Notification) { guard let pipController = notification.object as? AVPictureInPictureController else { return } if !pipController.isPictureInPictureActive { stopCamera() } } func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { stopCamera() } // 关闭相机的核心逻辑 private func stopCamera() { if captureSession?.isRunning == true { captureSession?.stopRunning() // 可添加其他清理操作,比如释放捕获设备资源、置空相关实例 } }
4. 清理通知监听
在控制器销毁时移除通知监听,避免内存泄漏:
deinit { NotificationCenter.default.removeObserver(self) } }
补充说明
- 边缘阈值可根据你的UI需求调整,阈值越小对滑动操作的检测越敏感;
- 如果需要在用户将PiP从边缘滑回时重新开启相机,可在
handlePiPFrameChange中增加反向位置判断逻辑; - 该方案兼容iOS 14及以上版本,若需支持更低版本,可提前检查通知的可用性。
内容的提问来源于stack exchange,提问作者bozkurt
相关产品推荐
相关产品推荐

