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

iPhone X及以上UIImagePickerController自定义cameraOverlayView被刘海遮挡适配安全区失效

适配UIImagePickerController自定义相机覆盖层的安全区显示

现有实现逻辑

你目前完成的自定义相机逻辑分为两部分:

自定义记录视图加载

cameraOverlay = RecordView.loadNib()
cameraOverlay.frame = UIScreen.main.bounds
cameraOverlay.buttonStartRecording.addTarget(self, action: #selector(buttonStartStopRecordingClicked),
                                             for: .touchUpInside)
cameraOverlay.buttonCancel.addTarget(self, action: #selector(buttonCancelClicked), for: .touchUpInside)
cameraOverlay.buttonSwitchCamera.addTarget(self, action: #selector(buttonCameraSwitchClicked), for: .touchUpInside)

cameraOverlay.buttonFlash.addTarget(self, action: #selector(buttonFlashClicked), for: .touchUpInside)
cameraOverlay.labelTimer.text = "00:00/\(self.secondsToHoursMinutesSeconds(inputSeconds: recordingTimeLimit))"

图片选择控制器配置

imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.mediaTypes = [kUTTypeMovie as String]
imagePicker.allowsEditing = true
imagePicker.cameraOverlayView = cameraOverlay
imagePicker.showsCameraControls = false
imagePicker.cameraFlashMode = .off
imagePicker.cameraCaptureMode = .video
imagePicker.cameraDevice = .rear
self.present(imagePicker, animated: true, completion: nil)

问题原因

给自定义覆盖层直接赋值UIScreen.main.bounds作为frame时,这个frame是覆盖整个物理屏幕的,包含了刘海、底部Home指示条的非交互区域。在无刘海老机型上这个范围刚好和有效显示区域重合所以运行正常,但在iPhone X及后续带安全区的机型上,靠近顶部的交互元素会直接落在刘海的遮挡范围内。

修复方案

替换硬编码全屏frame的逻辑

不要手动给覆盖层设置全屏幕frame,改用AutoLayout将覆盖层的边界约束到imagePicker视图的安全区内,修改后的代码逻辑:

  1. 删掉原来的cameraOverlay.frame = UIScreen.main.bounds这行代码
  2. 开启AutoLayout适配,将覆盖层四边和imagePicker的安全区做绑定:
cameraOverlay.translatesAutoresizingMaskIntoConstraints = false
imagePicker.cameraOverlayView = cameraOverlay
NSLayoutConstraint.activate([
    cameraOverlay.topAnchor.constraint(equalTo: imagePicker.view.safeAreaLayoutGuide.topAnchor),
    cameraOverlay.bottomAnchor.constraint(equalTo: imagePicker.view.safeAreaLayoutGuide.bottomAnchor),
    cameraOverlay.leadingAnchor.constraint(equalTo: imagePicker.view.safeAreaLayoutGuide.leadingAnchor),
    cameraOverlay.trailingAnchor.constraint(equalTo: imagePicker.view.safeAreaLayoutGuide.trailingAnchor)
])

落地注意事项

  • 不要在视图未完成布局时提前通过UIScreen.main.bounds或者keyWindow的safeAreaInsets计算边距值,这种场景下拿到的安全区边距往往是0,无法正确适配刘海区域。所有约束尽量以当前控制器的safeAreaLayoutGuide作为参考锚点,这种写法会自动兼容iOS 11以下的系统,在无刘海设备上会自动降级为普通视图边界,不需要手动判断设备型号。
  • UIImagePickerController的相机预览区域默认是铺满全屏幕的,如果你把覆盖层完全约束在安全区内,预览画面的上下部分会被覆盖层的不透明区域遮挡。可以根据实际UI设计调整覆盖层的边距:将不需要交互的透明区域放开到全屏幕范围,只把需要用户操作的按钮、计时器标签等元素单独约束在安全区内,兼顾预览效果和交互可用性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 02:06:04