swift自定义转场动画

在新浪微博的首页部分,点击用户名会向下弹出一个表格,如下图:

swift自定义转场动画_第1张图片
下拉视图.png

我用模态弹出视图,但是系统的效果是从下往上弹出的,所以我们需要通过自定义转场动画,来达到我们想要的效果.详细效果大家可以打开新浪微博试试哦(ps:我的新浪微博ID是:U小姐咯.四个字哦,如图所示,欢迎关注).
1⃣️.为了简洁代码,我们用xib搭配,首先创建一个 PopViewController并在xib拖入黑色带箭头的图片,并放上表格,进行一下适配.
2⃣️.接下来自定义一个 DMPresentationController继承于 UIPresentationController,代码如下

class DMPresentationController: UIPresentationController {

    //如果不自定义转场,modal出来的控制器会移除原有的控制器,自定义的则不会
    //自定义可以改变控制器的尺寸和屏幕不一样
    var presentFrame = CGRectZero
    override init(presentedViewController : UIViewController,presentingViewController : UIViewController) {
        super.init(presentedViewController: presentedViewController, presentingViewController: presentingViewController)
    }
    //用于布局转场动画弹出的控件
    override func containerViewWillLayoutSubviews() {
        //这个属性是容器,所有弹出的的视图都是放在这里面的
       //  containerView
       // presentedView()  通过方法拿到弹出视图
        presentedView()?.frame = presentFrame
        
        //添加蒙版,点击btn让图层收起来
       // containerView?.addSubview(coverBtn)
        //0代表最底层
        containerView?.insertSubview(coverBtn, atIndex: 0)
        coverBtn.addTarget(self, action: #selector(DMPresentationController.touch), forControlEvents: UIControlEvents.TouchUpInside)
    }
    
    func touch(){
presentedViewController.dismissViewControllerAnimated(true, completion: nil)
    }
    //MARK:懒加载
    private var coverBtn : UIButton = {
        let btn = UIButton.init(type: UIButtonType.Custom)
        btn.frame = UIScreen.mainScreen().bounds
        return btn
    }()
}

3⃣️.我们自定义了转场动画,还需要一个负责转场动画的对象,创建DMPresentationManager继承NSObject,管理我们需要的效果.代码如下:

class DMPresentationManager: NSObject,UIViewControllerTransitioningDelegate,UIViewControllerAnimatedTransitioning {
    var managerFrame = CGRectZero
    private var isPresent = false
    //该方法返回一个负责转场动画的对象
    //可以在该对象中控制弹出视图的尺寸
    func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController, sourceViewController source: UIViewController) -> UIPresentationController? {
        let presentVc = DMPresentationController.init(presentedViewController: presented, presentingViewController: presenting)
        presentVc.presentFrame = managerFrame
        return presentVc
    }
    //该方法用于返回一个负责转场如何出现的对象
    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning?{
        //遵守协议,消失就会调用
        isPresent = !isPresent
        //发送通知,通知状态发生改变
NSNotificationCenter.defaultCenter().postNotificationName(DMPresentationManagerPresented, object: self)
        return self
    }
    //用于返回一个负责转场如何消失的对象
    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?{
        isPresent = !isPresent
        NSNotificationCenter.defaultCenter().postNotificationName(DMPresentationManagerDismissed, object: self)
        return self
    }
    //MARK:UIViewControllerAnimatedTransitioning
    //告诉系统展现和小时的动画时长
    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval{
        //这个方法设置执行动画的时间
        return 0.3
    }
    //用于管理modal如何展现和消失,都会调用这个方法
    //只要实现了这个代理方法,系统就不会添加默认的动画,所有动画操作需要自己实现,包括需要展现的视图也需要自己添加到容器视图上(containerView)
    //transitionContext,所有动画都保存在上下文中,就是可以通过transitionContext获取我们想要的东西
    func animateTransition(transitionContext: UIViewControllerContextTransitioning){
        //展现或者消失都会调用这个方法
        
        if isPresent {
            //获取需要弹出视图
            //UITransitionContextFromViewKey, and UITransitionContextToViewKey
            presentAnimation(transitionContext)
        }else{
            
            dismissedAnimation(transitionContext)
        }
    }
    private func presentAnimation(transitionContext: UIViewControllerContextTransitioning){
        guard let toView = transitionContext.viewForKey(UITransitionContextToViewKey) else{
            return
        }
        //将需要弹出视图添加到containerView上
        transitionContext.containerView()?.addSubview(toView)
        //执行动画
        toView.transform = CGAffineTransformMakeScale(1.0, 0.0)
        //设置锚点
        toView.layer.anchorPoint = CGPoint(x: 0.5,y: 0)
        UIView.animateWithDuration(0.3, animations: { () ->Void in
            toView.transform = CGAffineTransformIdentity
        }) { (_)-> Void in  //下划线代表忽略这个值
            //自定义转场动画,执行完之后一定要告诉系统动画执行完毕了
            transitionContext.completeTransition(true)
        }
    }
    private func dismissedAnimation(transitionContext: UIViewControllerContextTransitioning){
        guard let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) else{
            return
        }
        UIView.animateWithDuration(1, animations: { () ->Void in
            fromView.transform = CGAffineTransformMakeScale(1.0, 0.000000)
        }) { (_)-> Void in  //下划线代表忽略这个值
            //自定义转场动画,执行完之后一定要告诉系统动画执行完毕了
            transitionContext.completeTransition(true)
        }
    }
}

4⃣️.接下来我们实现点击按钮可以弹出我们自定义的视图

let popVc = PopViewController()
        //自定义转场动画
        //设置代理
        popVc.transitioningDelegate = animationManager
        //设置样式
        popVc.modalPresentationStyle = UIModalPresentationStyle.Custom
        presentViewController(popVc, animated: true, completion: nil)

 //MARK:懒加载
    lazy var animationManager :DMPresentationManager = {
        let manager = DMPresentationManager()
 //这里我们对需要弹出视图的frame进行相应的设置
        manager.managerFrame = CGRectMake(100, 60, 200, 320)
        return manager
    }()

以上

你可能感兴趣的:(swift自定义转场动画)