iOS自定義轉(zhuǎn)場(chǎng)動(dòng)畫

ios8自定義轉(zhuǎn)場(chǎng)動(dòng)畫

  • 首先只能在iOS 8后使用

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


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

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

@available(iOS 8.0, *)

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

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


class CustomPopoverPresentationController: UIPresentationController {
    
    /**
    初始化方法, 用于創(chuàng)建負(fù)責(zé)轉(zhuǎn)場(chǎng)動(dòng)畫的對(duì)象
    
    :param: presentedViewController  被展現(xiàn)的控制器
    :param: presentingViewController 發(fā)起的控制器, Xocde6是nil, Xcode7是野指針
    
    :returns: 負(fù)責(zé)轉(zhuǎn)場(chǎng)動(dòng)畫的對(duì)象
    */
    override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
        super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
    }
    
    /**
    即將布局轉(zhuǎn)場(chǎng)子視圖時(shí)調(diào)用
    */
    override func containerViewWillLayoutSubviews()
    {
    
        // presentedView 表示為彈出的視圖,containerView 表示容器view
        // 1.修改彈出視圖的大小
        presentedView?.frame = CGRect(x: 100, y: 56, width: 200, height: 200)
        
        // 2.在容器視圖上添加一個(gè)蒙版, 插入到展現(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)聽(tīng)
        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.實(shí)現(xiàn)協(xié)議中另外兩個(gè)方法來(lái)自定義動(dòng)畫的實(shí)現(xiàn)

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

  • 自定義一個(gè)isPresent表示是否model出來(lái)了

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

5.由于UIViewControllerAnimatedTransitioning是協(xié)議,而設(shè)置了當(dāng)前控制器遵守協(xié)議,所以需要遵守協(xié)議實(shí)現(xiàn)方法,如下遵守UIViewControllerAnimatedTransitioning協(xié)議 ,實(shí)現(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)

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


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容