弹窗转场/过度动画(Popover效果)
避免浪费大家时间,快速查看运行效果可以直接拉到最后看 【五.完整代码】 部分,如果要看递推逻辑,可以从前往后看。
一.基本设置
弹出一个控制器:系统提供了以下的方法
@available(iOS 5.0, *)
open func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil)
但是如果想自定义弹出控制器的大小及动画的展示形式,就需要自定义转场
首先UIModalPresentationStyle定义了控制器弹出的方式
@available(iOS 3.2, *)
open var modalPresentationStyle: UIModalPresentationStyle
要设置为**.custom**,这样弹出控制器后,背后的控制器不会消失,如下:
二.调整大小
//popoverVc是将要弹出来的控制器
popoverVc.modalPresentationStyle = .custom
其次要使控制器遵守转场动画的协议:UIViewControllerTransitioningDelegate
@available(iOS 2.0, *)
optional func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
@available(iOS 2.0, *)
optional func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
optional func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?
optional func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?
@available(iOS 8.0, *)
optional func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController?
协议中先看下第五个方法,此方法中,我们可以拿到要弹出的控制器和被弹出的控制器,返回值是UIPresentationController
可以认为,系统就是通过这个类型的控制器将我们要弹出的控制器,弹出来的。所以我们自定义一个控制器,继承自UIPresentationController,然后就改变一些东西,比如弹出控制器view的大小:
open var presentingViewController: UIViewController {
get }
open var presentedViewController: UIViewController {
get }
// The view in which a presentation occurs. It is an ancestor of both the presenting and presented view controller's views.
// This view is being passed to the animation controller.
open var containerView: UIView? {
get }
// A view that's going to be animated during the presentation. Must be an ancestor of a presented view controller's view
// or a presented view controller's view itself.
// (Default: presented view controller's view)
open var presentedView: UIView? {
get }
可以看到,我们可以拿到要弹出来的控制器presentedViewController和它的view presentedView,那么我们改变presentedView的frame,就可以调整弹出控制器的位置大小了。自定义示例如下:
import UIKit
class WXPresentationController: UIPresentationController {
//提供属性,frame由外界传入
var presentedFrame:CGRect = CGRect(x: 0, y: 0, width: 0, height: 0)
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
presentedView!.frame = presentedFrame
setupCoverView()
}
}
/MARK:- 添加蒙版
extension WXPresentationController{
private func setupCoverView(){
let coverView = UIView(frame: containerView!.bounds)
coverView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.2)