如何将已展示的模态视图控制器临时切换成全屏再恢复?
动态切换模态视图控制器的全屏/标准样式
直接用系统API就能实现,不用自定义容器或转场,核心是调整模态样式+配合视图动画,同时处理拖拽手势和视觉细节,以下是完整实现:
代码实现
class A: UIViewController { private var isFullScreen = false override func viewDidLoad() { super.viewDidLoad() presentationController?.delegate = self } @objc func goFullScreen(sender: UIButton) { guard !isFullScreen else { return } isFullScreen = true // 拦截拖拽关闭手势,隐藏顶部抓握条 if let sheetPC = presentationController as? UISheetPresentationController { sheetPC.isModalInPresentation = true sheetPC.prefersGrabberVisible = false } // 切换为全屏模态样式 modalPresentationStyle = .fullScreen // 动画过渡到全屏状态 UIView.animate(withDuration: 0.3) { self.view.layer.cornerRadius = 0 self.view.frame = UIScreen.main.bounds self.view.layoutIfNeeded() } // 这里添加你需要隐藏的UI操作 // topToolbar.isHidden = true } @objc func cancelFullScreen(sender: UIButton) { guard isFullScreen else { return } isFullScreen = false // 恢复拖拽关闭手势,显示顶部抓握条 if let sheetPC = presentationController as? UISheetPresentationController { sheetPC.isModalInPresentation = false sheetPC.prefersGrabberVisible = true } // 切回标准pageSheet样式 modalPresentationStyle = .pageSheet // 动画恢复到标准模态外观 UIView.animate(withDuration: 0.3) { self.view.layer.cornerRadius = 16 // 系统默认pageSheet圆角 self.view.frame = self.presentationController?.containerView?.bounds ?? self.view.frame self.view.layoutIfNeeded() } // 恢复显示UI元素 // topToolbar.isHidden = false } } // 实现代理控制拖拽关闭逻辑 extension A: UIAdaptivePresentationControllerDelegate { func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { // 全屏状态下禁止拖拽关闭 return !isFullScreen } }
关键细节说明
- 模态样式切换:直接修改
modalPresentationStyle后,用动画同步视觉变化,避免生硬跳转。系统会自动适配样式对应的布局容器,我们只需要调整自身view的frame和圆角即可。 - 拖拽手势控制:iOS 15+的标准模态由
UISheetPresentationController实现,通过isModalInPresentation属性控制是否允许拖拽关闭,全屏时设为true拦截手势,恢复时设为false。同时隐藏/显示顶部抓握条增强视觉一致性。 - 视觉过渡:动画时长和系统模态过渡保持一致(0.3秒),圆角设为系统默认的16pt,保证和原生模态外观统一。
- 保持同一实例:全程不需要dismiss再present,所有修改都在当前VC上完成,确保状态不丢失。
注意点
- 如果需要兼容iOS 14及以下,标准模态的底层是
UIPresentationController,可以直接修改containerView的布局,或者用AutoLayout约束代替直接设置frame,避免适配问题。 - 若使用AutoLayout,动画时只需要修改约束常量,然后调用
layoutIfNeeded()即可,比直接设置frame更稳定。
内容的提问来源于stack exchange,提问作者Nik
相关产品推荐
相关产品推荐

