自訂presentViewController的轉場動畫(Swift)

來源:互聯網
上載者:User

自訂presentViewController的轉場動畫(Swift)
前言:

iOS預設的presentViewController的切換動畫是從底部推入,消失是從頂部推出。但是,因為iOS系統預設的是適配所有轉場內容相關的。而針對特定的轉場上下文,我們能做出更好的效果。

Tips:所謂的轉場上下文,就是轉場的開始View和結束View,以及對應的ViewController

目標效果

最終的效果

準備工作

首先寫出一個CollectionView,每個Cell是一個圖片,由於本文的核心是如何轉場,所以CollectionView的部分略過。寫完了之後,是這樣的效果

點擊某一個CollectionView Cell查看大圖,再點擊大圖圖片消失

 

如何?自訂轉場動畫

iOS 8之後,我們可以通過設定ViewControllertransitioningDelegate來設定代理來處理轉場動畫。

通過文檔,可以看到transitioningDelegate是一個實現UIViewControllerTransitioningDelegate協議的對象,先看看這個協議,本文主要利用以下兩個方法

animationControllerForDismissedController animationControllerForPresentedController

著兩個方法的目的是,提供一個遵循UIViewControllerAnimatedTransitioning協議的對象,然後又這個對象來實際處理專場。通過名字就可以看出來,一個是處理present一個是處理dismiss。

本文的設計是讓ViewController來處理轉場,在didSelectItemAtIndexPath中,設定pvc的轉場代理

dvc.transitioningDelegate = self

然後,寫一個extension來實現協議

extension ViewController:UIViewControllerTransitioningDelegate{    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {        return nil    }    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {        return nil    }}

這時候,再運行項目,會發現沒有任何變化,還是預設的轉場方式。因為我們還沒有提供實際的動畫 。當上述兩個代理方法返回nil的時候,系統會使用預設的方式

實現UIViewControllerAnimatedTransitioning

建立一個檔案,命名為Animator.swift,然後建立一個類,處理Present的轉場(Dismiss類似),實現UIViewControllerAnimatedTransitioning協議

class PresentAnimator: NSObject,UIViewControllerAnimatedTransitioning{}

這時候,會報錯沒有實現協議,然後,我們添加協議方法,這時候的Animator.swift如下

import Foundationimport UIKitclass PresentAnimator: NSObject,UIViewControllerAnimatedTransitioning{    let duration = 0.5 //動畫的時間    var originFrame = CGRectZero //點擊Cell的frame    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {        return duration    }    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {    }}

簡單介紹下這裡的協議方法

transitionDuration,返迴轉場動畫的時間 animateTransition,進行實際的轉場動畫,通過參數transitionContext(轉場上下文)來擷取轉場的fromView,toView,fromViewController,toViewController。轉場的原理

轉場開始的時候,自動把FromView添加到轉場ContainView 轉場結束的時候,自動把FromView移除ContainView

所以,開發人員要做的就是

把toView添加到轉場ContainView中,並且定義好toView的初始位置和狀態 定義好FromView和ToView的轉場結束時候的狀態 建立動畫實現實際的轉場動畫

基於上述的原理,我們修改實際的動畫

     func animateTransition(transitionContext: UIViewControllerContextTransitioning) {        let containView = transitionContext.containerView()        let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!        let finalFrame = toView.frame        let xScale = originFrame.size.width/toView.frame.size.width        let yScale = originFrame.size.height/toView.frame.size.height        toView.transform = CGAffineTransformMakeScale(xScale, yScale)        toView.center = CGPointMake(CGRectGetMidX(originFrame), CGRectGetMidY(originFrame))        containView?.addSubview(toView)        UIView.animateWithDuration(duration, animations: { () -> Void in            toView.center = CGPointMake(CGRectGetMidX(finalFrame), CGRectGetMidY(finalFrame))            toView.transform = CGAffineTransformIdentity            }) { (finished) -> Void in                transitionContext.completeTransition(true)        }    }

然後,在ViewController.swfit中,添加一屬性

    let presentAnimator = PresentAnimator()

修改didSelectItemAtIndexPath

    override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {        let dvc = DetailViewController()        dvc.image = UIImage(named: "image.jpg")        dvc.transitioningDelegate = self        let cell =  collectionView.cellForItemAtIndexPath(indexPath) as! FullImageCell        presentAnimator.originFrame = cell.convertRect(cell.imageview.frame, toView: nil)        self.presentViewController(dvc, animated: true, completion: nil)    }

修改代理方法

    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {        return presentAnimator    }

這時候的動畫效果如Gif

同理,為dismiss添加轉場動畫

在Animator.swift中添加一個新的類

class DismisssAnimator:NSObject,UIViewControllerAnimatedTransitioning{    let duration = 0.6    var originFrame = CGRectZero    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {        return duration    }    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {        let containView = transitionContext.containerView()        let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! //Collection View        let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! //全屏的imageview        let xScale = originFrame.size.width/toView.frame.size.width        let yScale = originFrame.size.height/toView.frame.size.height        containView?.addSubview(toView)        containView?.bringSubviewToFront(fromView)        UIView.animateWithDuration(duration, animations: { () -> Void in            fromView.center = CGPointMake(CGRectGetMidX(self.originFrame), CGRectGetMidY(self.originFrame))            fromView.transform = CGAffineTransformMakeScale(xScale, yScale)            }) { (finished) -> Void in                transitionContext.completeTransition(true)        }    }}

然後,在ViewController.swift中didSelectItemAtIndexPath設定presentAnimator.frame下一行添加

 dismissAnimator.originFrame = cell.convertRect(cell.imageview.frame, toView: nil)

其中,dismissAnimator是ViewController的一個屬性

    let dismissAnimator = DismisssAnimator()

然後,在代理方法中,返回

 func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {        return dismissAnimator;    }

最終的效果

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.