原文鏈接
轉場動畫
需求:
- 點擊導航欄左上角,出現(xiàn)一個左側菜單
- 左側菜單覆蓋住 原控制器的一半
- 左側菜單的出現(xiàn)順序為:從左至右
實現(xiàn)
- 左側菜單為 UIViewController,
- UIViewController 半透明狀態(tài)伞访,可以看到 原控制器的數(shù)據(jù)
- 使用轉場動畫實現(xiàn)左側菜單的動畫效果
- 使用 modalPresentationStyle 做出 半透明效果
- ViewController 控制器為 第一控制器侨把, 以后簡稱 A控制器。
- SecondVC 控制器為 第二控制器,以后簡稱 B控制器
- FadeAnimator 類 是 用來寫 轉場動畫的類诊胞。
demo地址
實現(xiàn)代碼
- 在 FadeAnimator 類中實現(xiàn) 動畫,代碼如下:
//
// FadeAnimator.swift
// LeftView
//
// Created by study on 2017/6/30.
// Copyright ? 2017年 WY. All rights reserved.
//
import UIKit
enum AnimationType {
case present
case dismiss
}
class FadeAnimator: NSObject , UIViewControllerAnimatedTransitioning {
let duration = 1.5
var animationType: AnimationType?
// 指定轉場動畫持續(xù)的時間
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
let toView = toViewController?.view
let fromView = fromViewController?.view
let transitionTime = transitionDuration(using: transitionContext)
let aDelay: TimeInterval = 0
let aUsing: CGFloat = 0.5
let aInitSprVel: CGFloat = 0
if animationType == AnimationType.present {
//snapshot方法是很高效的截屏
// first 放下面
let snap = fromView?.snapshotView(afterScreenUpdates: true)
transitionContext.containerView.addSubview(snap!)
//Third放上面
let snap2 = toView?.snapshotView(afterScreenUpdates: true)
transitionContext.containerView.addSubview(snap2!)
snap2?.transform = CGAffineTransform(translationX: -320, y: 0)
UIView.animate(withDuration: transitionTime, delay: aDelay, usingSpringWithDamping: aUsing, initialSpringVelocity: aInitSprVel, options: UIViewAnimationOptions.curveLinear, animations: {
snap2?.transform = CGAffineTransform.identity
}, completion: { (finished) in
// 刪掉截圖
snap?.removeFromSuperview()
snap2?.removeFromSuperview()
// 添加視圖
transitionContext.containerView.addSubview(toView!)
// 結束 Transition
let aDidCom = transitionContext.transitionWasCancelled
transitionContext.completeTransition(!aDidCom)
})
}
else {
// Third 放下面
let snap = toView?.snapshotView(afterScreenUpdates: true)
transitionContext.containerView.addSubview(snap!)
// first 放上面
let snap2 = fromView?.snapshotView(afterScreenUpdates: true)
transitionContext.containerView.addSubview(snap2!)
//進行動畫
UIView.animate(withDuration: transitionTime, delay: aDelay, usingSpringWithDamping: aUsing, initialSpringVelocity: aInitSprVel, options: UIViewAnimationOptions.curveLinear, animations: {
snap2?.transform = CGAffineTransform(translationX: -320, y: 0)
}, completion: { (finished) in
// 刪掉截圖
snap?.removeFromSuperview()
snap2?.removeFromSuperview()
//添加視圖
transitionContext.containerView.addSubview(fromView!)
//結束Transition
let aDidCom = transitionContext.transitionWasCancelled
transitionContext.completeTransition(!aDidCom)
})
}
}
}
- 在A控制器中 創(chuàng)建一個按鈕锹杈,用來跳轉到B頁面:
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton(type: .contactAdd)
btn.frame = view.bounds
btn.setTitle("跳轉第二頁", for: .normal)
btn.addTarget(self, action: #selector(clickBtn), for: .touchUpInside)
self.view.addSubview(btn)
}
- 在 跳轉的方法中 半透明效果
func clickBtn(){
let secod = SecondVC()
/// 半透明效果
self.modalPresentationStyle = .custom
self.definesPresentationContext = true
secod.view.backgroundColor = UIColor.init(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: 0.5)
/// 半透明效果
secod.modalPresentationStyle = .overCurrentContext
/// 轉場動畫的代理撵孤,在 A類中實現(xiàn)
secod.transitioningDelegate = self
/// 使用 present 進行跳轉
present(secod, animated: true, completion: nil)
}
- 轉場動畫的代理,在A類中實現(xiàn)
extension ViewController: UIViewControllerTransitioningDelegate {
// 提供彈出時的動畫
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
transition.animationType = AnimationType.present
return transition
}
// 提供消失時的動畫
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
transition.animationType = AnimationType.dismiss
return transition
}
}
- B控制器中實現(xiàn)的代碼只有 一個返回按鈕(demo中)
//
// SecondVC.swift
// LeftView
//
// Created by study on 2017/6/30.
// Copyright ? 2017年 WY. All rights reserved.
//
import UIKit
class SecondVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton(type: .contactAdd)
btn.frame = CGRect(x: 50, y: 100, width: 200, height: 100)
btn.setTitle("回到第一頁", for: .normal)
btn.backgroundColor = UIColor.red
btn.addTarget(self, action: #selector(clickBtn), for: .touchUpInside)
self.view.addSubview(btn)
}
func clickBtn(){
dismiss(animated: true, completion: nil)
}
}
------------------- 我是懶惰的分界線----------------
下列方法也可以進行跳轉嬉橙,只需要把 present (XXX)方法替換成此方法就好早直,缺點是寥假,跳轉的時候會有黑色的一閃而過
import UIKit
extension UIViewController {
/// 從左到右
func presentDetailFromeLeftToRight(_ viewControllerToPresent: UIViewController) {
let animation = CATransition()
animation.duration = 0.5
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromLeft
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
self.view.window?.layer.add(animation, forKey: kCATransition)
present(viewControllerToPresent, animated: false, completion: nil)
}
/// 從右到左
func dismissDetailFromeRightToLeft(){
let animation = CATransition()
animation.duration = 0.5
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromRight
self.view.window?.layer.add(animation, forKey: kCATransition)
dismiss(animated: false, completion: nil)
}
}