子类化UIPresentationController时如何使用Auto-Layout实现弹窗布局?
嘿,我完全懂你这种不想手动算frame的心情——既繁琐又容易在旋转、尺寸变化时出问题!其实UIPresentationController里是有办法结合自动布局来搞定这个的,不用一直跟CGRect打交道,我给你捋捋具体怎么做:
核心思路:用容器视图+自动布局替代手动计算Frame
UIPresentationController的containerView是关键,我们可以把弹出的VC视图加到这个容器里,然后直接给它加约束,让它被限制在presenting VC的范围内,不用手动算size或者frame。
步骤1:重写presentationTransitionWillBegin()配置约束
在这个方法里,我们可以拿到presented VC的view,把它加到containerView里,然后设置好约束。比如:
override func presentationTransitionWillBegin() { super.presentationTransitionWillBegin() // 获取presented视图,关闭自动转译mask,避免和自动布局冲突 let presentedView = presentedViewController.view presentedView.translatesAutoresizingMaskIntoConstraints = false containerView?.addSubview(presentedView) // 添加约束,让presented视图被限制在presenting VC的frame内 // 这里可以根据需求调整,比如留边距、居中,或者直接贴合 NSLayoutConstraint.activate([ presentedView.topAnchor.constraint(equalTo: containerView!.topAnchor), presentedView.leadingAnchor.constraint(equalTo: containerView!.leadingAnchor), presentedView.trailingAnchor.constraint(equalTo: containerView!.trailingAnchor), presentedView.bottomAnchor.constraint(equalTo: containerView!.bottomAnchor) ]) // 如果需要过渡动画,可以配合transitionCoordinator实现 if let coordinator = presentingViewController.transitionCoordinator { coordinator.animate(alongsideTransition: { _ in // 这里可以加动画相关的属性变化,比如alpha从0到1 presentedView.alpha = 1 }, completion: nil) } else { presentedView.alpha = 1 } }
步骤2:重写size(forChildContentContainer:withParentContainerSize:)返回动态尺寸
虽然我们用了自动布局,但UIPresentationController还是会询问这个尺寸,我们可以让它根据presenting VC的大小和自动布局规则动态返回:
override func size(forChildContentContainer container: UIContentContainer, withParentContainerSize parentSize: CGSize) -> CGSize { // 让系统根据自动布局约束计算最合适的尺寸 return presentedViewController.view.systemLayoutSizeFitting(parentSize) }
步骤3:处理旋转和尺寸变化
如果你的App支持旋转或分屏,重写containerViewWillLayoutSubviews()确保布局在尺寸变化时自动更新:
override func containerViewWillLayoutSubviews() { super.containerViewWillLayoutSubviews() // 强制刷新presented视图的布局,确保约束生效 presentedViewController.view.layoutIfNeeded() }
额外技巧:限制弹出视图的最大尺寸
如果你不想让弹出视图占满整个presenting VC,还可以给它加最大宽度/高度的约束,比如:
// 在presentationTransitionWillBegin方法里添加 let maxWidthConstraint = presentedView.widthAnchor.constraint(lessThanOrEqualToConstant: 350) let maxHeightConstraint = presentedView.heightAnchor.constraint(lessThanOrEqualToConstant: 500) // 让弹出视图居中(可选) let centerXConstraint = presentedView.centerXAnchor.constraint(equalTo: containerView!.centerXAnchor) let centerYConstraint = presentedView.centerYAnchor.constraint(equalTo: containerView!.centerYAnchor) NSLayoutConstraint.activate([maxWidthConstraint, maxHeightConstraint, centerXConstraint, centerYConstraint])
这样一来,你就不用再手动计算frame了,所有的布局都交给自动布局来处理,旋转、尺寸变化的时候也能自动适配,比手动算靠谱多了!
内容的提问来源于stack exchange,提问作者Alex Bollbach
相关产品推荐
相关产品推荐

