UIPresentationController底部弹窗取消保存后短暂全屏问题求助
解决自定义弹窗关闭“保存到文件”后短暂全屏的问题
嘿,这个坑我之前踩过!用UIPresentationController做底部自定义弹窗时,调用系统的“保存到文件”后确实会出现弹窗先闪全屏再恢复的情况,本质是系统处理模态转场时临时修改了presentedView的尺寸,而原来的布局逻辑没跟上。下面是我亲测有效的解决思路:
核心解决思路
- 用约束替代直接设置Frame:别再只在
containerViewWillLayoutSubviews()里硬写frame了,直接给presentedView添加明确的宽度、高度和位置约束,让系统无法随意修改它的尺寸。 - 重写尺寸计算方法:在自定义的PresentationController里重写
size(forChildContentContainer:withParentContainerSize:),返回你想要的弹窗尺寸,告诉系统这才是弹窗的理想大小。 - 避免布局逻辑滞后:系统在关闭“保存到文件”视图后才触发
containerViewWillLayoutSubviews(),这时候已经晚了,提前用约束和尺寸方法锁定布局,就能避免临时全屏的闪屏。
修改后的关键代码
自定义PresentationController
class SlideInPresentationController: UIPresentationController { private let direction: PresentationDirection private let disableCompactHeight: Bool init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?, direction: PresentationDirection, disableCompactHeight: Bool) { self.direction = direction self.disableCompactHeight = disableCompactHeight super.init(presentedViewController: presentedViewController, presenting: presentingViewController) } // 告诉系统弹窗的理想尺寸 override func size(forChildContentContainer container: UIContentContainer, withParentContainerSize parentSize: CGSize) -> CGSize { // 根据你的需求返回自定义尺寸,比如高度300,宽度和父容器一致 if disableCompactHeight && traitCollection.horizontalSizeClass == .compact && traitCollection.verticalSizeClass == .regular { return CGSize(width: parentSize.width, height: 300) } return super.size(forChildContentContainer: container, withParentContainerSize: parentSize) } override func containerViewWillLayoutSubviews() { super.containerViewWillLayoutSubviews() guard let presentedView = presentedView else { return } // 禁用自动转译,用约束控制布局 presentedView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ presentedView.widthAnchor.constraint(equalTo: containerView!.widthAnchor), presentedView.heightAnchor.constraint(equalToConstant: 300), // 替换成你的弹窗高度 presentedView.bottomAnchor.constraint(equalTo: containerView!.bottomAnchor) // 底部弹出的位置约束 ]) } // 可选:添加背景遮罩(如果需要的话) override func presentationTransitionWillBegin() { super.presentationTransitionWillBegin() let dimmingView = UIView() dimmingView.backgroundColor = UIColor.black.withAlphaComponent(0.5) dimmingView.frame = containerView!.bounds dimmingView.autoresizingMask = [.flexibleWidth, .flexibleHeight] containerView?.insertSubview(dimmingView, at: 0) } }
确保TransitioningDelegate返回正确的PresentationController
class SlideInPresentationManager: NSObject, UIViewControllerTransitioningDelegate { var direction: PresentationDirection = .bottom var disableCompactHeight = true func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return SlideInPresentationController(presentedViewController: presented, presenting: presenting, direction: direction, disableCompactHeight: disableCompactHeight) } }
为什么这样有效?
系统在处理“保存到文件”这种系统级模态视图时,会临时调整presentedView的尺寸来适配转场,但我们通过size(forChildContentContainer:)明确告诉了系统弹窗的理想尺寸,再加上约束锁定了位置和大小,系统就不会随便把弹窗拉成全屏了,关闭后也能保持正确的布局,不会出现闪屏。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

