iOS自定義轉(zhuǎn)場動畫

ios8自定義轉(zhuǎn)場動畫

  • 首先只能在iOS 8后使用

    默認情況下modal會移除以前控制器的view, 替換為當(dāng)前彈出的view
    如果自定義轉(zhuǎn)場, 那么就不會移除以前控制器的view


// vc是要被model的控制器
let vc = UIViewController() 
// 設(shè)置轉(zhuǎn)場代理為當(dāng)前控制器
vc?.transitioningDelegate = self
        
// 設(shè)置轉(zhuǎn)場的樣式為自定義
vc?.modalPresentationStyle = UIModalPresentationStyle.custom
        
present(vc!, animated: true, completion: nil)

1.遵守UIViewControllerTransitioningDelegate協(xié)議瘦锹,實現(xiàn)協(xié)議方法列赎, 設(shè)置轉(zhuǎn)場樣式為自定義

@available(iOS 8.0, *)

optional public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController?

2.要返回一個UIPresentationController,所以自頂一個類繼承UIPresentationController


class CustomPopoverPresentationController: UIPresentationController {
    
    /**
    初始化方法, 用于創(chuàng)建負責(zé)轉(zhuǎn)場動畫的對象
    
    :param: presentedViewController  被展現(xiàn)的控制器
    :param: presentingViewController 發(fā)起的控制器, Xocde6是nil, Xcode7是野指針
    
    :returns: 負責(zé)轉(zhuǎn)場動畫的對象
    */
    override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
        super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
    }
    
    /**
    即將布局轉(zhuǎn)場子視圖時調(diào)用
    */
    override func containerViewWillLayoutSubviews()
    {
    
        // presentedView 表示為彈出的視圖,containerView 表示容器view
        // 1.修改彈出視圖的大小
        presentedView?.frame = CGRect(x: 100, y: 56, width: 200, height: 200)
        
        // 2.在容器視圖上添加一個蒙版, 插入到展現(xiàn)視圖的下面
        containerView?.insertSubview(coverView, at: 0)
    }
    
    // MARK: - 懶加載
    fileprivate lazy var coverView: UIView = {
        // 1.創(chuàng)建view
       let view = UIView()
        view.backgroundColor = UIColor(white: 0.0, alpha: 0.2)
        view.frame = UIScreen.main.bounds
        
        // 2.添加監(jiān)聽
        let tap = UITapGestureRecognizer(target: self, action: "close")
        view.addGestureRecognizer(tap)
        return view
    }()
    
    func close(){
        // presentedViewController拿到當(dāng)前彈出的控制器
        presentedViewController.dismiss(animated: true, completion: nil)
    }
}

3.返回的UIPresentationController就用自定義類創(chuàng)建

    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController?
    {
        return CustomPopoverPresentationController(presentedViewController: presented, presenting: presenting)
    }

4.實現(xiàn)協(xié)議中另外兩個方法來自定義動畫的實現(xiàn)

  • 只要實現(xiàn)了以下方法, 那么系統(tǒng)自帶的默認動畫就沒有了, "所有"東西都需要程序員自己來實現(xiàn)

  • 自定義一個isPresent表示是否model出來了

@available(iOS 2.0, *) // 即將彈出
optional public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?

    
@available(iOS 2.0, *) // 即將消失
optional public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?



/**
告訴系統(tǒng)誰來負責(zé)Modal的展現(xiàn)動畫
:param: presented  被展現(xiàn)視圖
:param: presenting 發(fā)起的視圖
:returns: 誰來負責(zé)
*/
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
{
    isPresent = true
    return self
}
    
/**
告訴系統(tǒng)誰來負責(zé)Modal的消失動畫
:param: dismissed 被關(guān)閉的視圖
:returns: 誰來負責(zé)
*/
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?
{
    isPresent = false
    return self
}

5.由于UIViewControllerAnimatedTransitioning是協(xié)議沮焕,而設(shè)置了當(dāng)前控制器遵守協(xié)議幕帆,所以需要遵守協(xié)議實現(xiàn)方法岩榆,如下遵守UIViewControllerAnimatedTransitioning協(xié)議 窥翩,實現(xiàn)方法

public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval

// This method can only  be a nop if the transition is interactive and not a percentDriven interactive transition.
public func animateTransition(using transitionContext: UIViewControllerContextTransitioning)

// 實現(xiàn)方法
    // MARK: - UIViewControllerAnimatedTransitioning
    /**
    返回動畫時長
    
    :param: transitionContext 上下文, 里面保存了動畫需要的所有參數(shù)
    
    :returns: 動畫時長
    */
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval
    {
        return 0.5
    }
    
    /**
    告訴系統(tǒng)如何動畫, 無論是展現(xiàn)還是消失都會調(diào)用這個方法
    
    :param: transitionContext 上下文, 里面保存了動畫需要的所有參數(shù)
    */
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
    {
        // 1.拿到展現(xiàn)視圖
        /*
        let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
        let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
        // 通過打印發(fā)現(xiàn)需要修改的就是toVC上面的View
        print(toVC)
        print(fromVC)
        */
        if isPresent
        {
            // 展開
            print("展開")
            let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)!
            toView.transform = CGAffineTransform(scaleX: 1.0, y: 0.0);
            
            // 注意: 一定要將視圖添加到容器上
            transitionContext.containerView.addSubview(toView)
            
            // 設(shè)置錨點
            toView.layer.anchorPoint = CGPoint(x: 0.5, y: 0)
            
            // 2.執(zhí)行動畫
            UIView.animate(withDuration: 0.5, animations: { () -> Void in
                // 2.1清空transform
                toView.transform = CGAffineTransform.identity
                }, completion: { (_) -> Void in
                    // 2.2動畫執(zhí)行完畢, 一定要告訴系統(tǒng)
                    // 如果不寫, 可能導(dǎo)致一些未知錯誤
                    transitionContext.completeTransition(true)
            }) 
        }else
        {
            // 關(guān)閉
            print("關(guān)閉")
            let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)
            
            UIView.animate(withDuration: 0.2, animations: { () -> Void in
                // 注意:由于CGFloat是不準確的, 所以如果寫0.0會沒有動畫
                // 壓扁
                fromView?.transform = CGAffineTransform(scaleX: 1.0, y: 0.000001)
                }, completion: { (_) -> Void in
                    // 如果不寫, 可能導(dǎo)致一些未知錯誤
                    transitionContext.completeTransition(true)
            })
        }
    }


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末各薇,一起剝皮案震驚了整個濱河市项贺,隨后出現(xiàn)的幾起案子君躺,更是在濱河造成了極大的恐慌,老刑警劉巖开缎,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棕叫,死亡現(xiàn)場離奇詭異,居然都是意外死亡奕删,警方通過查閱死者的電腦和手機俺泣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來完残,“玉大人伏钠,你說我怎么就攤上這事〗魃瑁” “怎么了熟掂?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扎拣。 經(jīng)常有香客問我赴肚,道長,這世上最難降的妖魔是什么鹏秋? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任尊蚁,我火速辦了婚禮,結(jié)果婚禮上侣夷,老公的妹妹穿的比我還像新娘横朋。我一直安慰自己,他們只是感情好百拓,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布琴锭。 她就那樣靜靜地躺著,像睡著了一般衙传。 火紅的嫁衣襯著肌膚如雪决帖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天蓖捶,我揣著相機與錄音地回,去河邊找鬼。 笑死俊鱼,一個胖子當(dāng)著我的面吹牛刻像,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播并闲,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼细睡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了帝火?” 一聲冷哼從身側(cè)響起溜徙,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤湃缎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蠢壹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嗓违,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年知残,在試婚紗的時候發(fā)現(xiàn)自己被綠了靠瞎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡求妹,死狀恐怖乏盐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情制恍,我是刑警寧澤父能,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站净神,受9級特大地震影響何吝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鹃唯,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一爱榕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坡慌,春花似錦黔酥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至熄求,卻和暖如春渣玲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背弟晚。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工忘衍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卿城。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓淑履,卻偏偏與公主長得像,于是被迫代替她去往敵國和親藻雪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容