概述
基本上苹果提供的控制器转场都能满足我们的需求,比如反转、淡入淡出、翻页、从下往上显示等等,这都可以通过设置控制器实现。
但如果有一些特殊的需求,比如只在一小块区域显示新控制器的内容。当然你也可以通过一些复杂的方式在原本的控制器上自定义一个小View来实现,但那样会增加原控制器的业务负担。
实际上,我们可以通过自定义UIPresentationController来控制新controller的展示形式,这只需要在转场相关的代码部分设置一下代理,原控制器再遵守以下该转场控制器的协议就可以了。
具体
let accountVC = AccountController()
accountVC.modalPresentationStyle = .custom
accountVC.view.backgroundColor = UIColor.systemOrange
accountVC.transitioningDelegate = self
present(accountVC, animated: false) {
//TODO:
}
给底层的控制器写个拓展,遵守协议:
这里的底层指的是 弹出的上层控制器的上级控制器
extension BasicController:UIViewControllerTransitioningDelegate{
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return UIPresentationController(presentedViewController: presented, presenting: presenting)
}
}
我们需要重新定义UIPresentationController,创建一个新子类继承自UIPresentationController。
class LeftSlideController: UIPresentationController {
private lazy var coverView = UIView()
//containerView容器View完成好布局之后,调用
override func containerViewDidLayoutSubviews() {
super.containerViewDidLayoutSubviews()
//被弹出的View presentedView
let frame = UIScreen.main.bounds
presentedView?.frame.origin.x = frame.size.width
setupCoverView()
}
func setupCoverView(){
containerView?.insertSubview(coverView, at: 0)
coverView.backgroundColor = UIColor.init(white: 0.9, alpha: 0.1)
coverView.frame = containerView!.bounds
//添加退出手势
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissController))
coverView.addGestureRecognizer(tap)
}
@objc func dismissController(){
presentedViewController.dismiss(animated: false) {
}
}
}
然后回到控制器遵守转场动画协议的地方,修改返回对象为刚创建的新子类。
extension BasicController:UIViewControllerTransitioningDelegate{
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return LeftSlideController(presentedViewController: presented, presenting: presenting)
}
}