Swift ViewControllerTransitions
程序员文章站
2024-03-23 12:02:16
...
自定义Modally转场动画
准备
delegate转交给viewcontroller而不是系统
vc.transitioningDelegate = self
遵循协议
extension MainViewController:UIViewControllerTransitioningDelegate {
//出现的函数,返回一个UIViewControllerAnimatedTransitioning的一个动画器,于是就新建一个
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return PresentAnimator()
}
//退出的函数,同上返回一个动画器
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return DismissAnimator()
}
}
两个动画器
创建动画器
遵循两个协议
完成两个固定方法,一个设置动画经过时间,一个设置动画逻辑
class PresentAnimator:NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {}
}
完成动画器
PresentAnimator:
class PresentAnimator:NSObject, UIViewControllerAnimatedTransitioning {
//动画的经过时间
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
//动画逻辑
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard
//转场开始的vc
// let fromVC = transitionContext.viewController(forKey: .from),
//转场开始vc的根视图
let fromView = transitionContext.view(forKey: .from),
//转场结束的vc
// let toVC = transitionContext.viewController(forKey: .to),
//转场结束的vc的根视图
let toView = transitionContext.view(forKey: .to)
else{return}
//类似于NavigationView
let containerView = transitionContext.containerView
//加入toView,UIKit会自动加入fromView
containerView.addSubview(toView)
toView.alpha = 0
toView.transform = CGAffineTransform(translationX: containerView.frame.width, y: 0)
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
animations: {
fromView.alpha = 0
fromView.transform = CGAffineTransform(translationX: -containerView.frame.width, y: 0)
toView.alpha = 1
toView.transform = .identity
}) { _ in
fromView.transform = .identity
toView.transform = .identity
//UIKit调用这个方法来结束转场动画
transitionContext.completeTransition(true)
}
}
//tcontainerView在动画结束的时候会自动移除fromView只剩下toView,一旦toView被dismiss就会黑屏,但是fromView的transform属性还在,所以在最后要给他还原
}
DismissAnimator:
class DismissAnimator: NSObject,UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard
let fromView = transitionContext.view(forKey: .from),
let toView = transitionContext.view(forKey: .to)
else{return}
let containerView = transitionContext.containerView
containerView.addSubview(toView)
toView.alpha = 0
toView.transform = CGAffineTransform(translationX: -containerView.frame.width, y: 0)
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
animations: {
toView.alpha = 1
toView.transform = .identity
fromView.alpha = 0
fromView.transform = CGAffineTransform(translationX: containerView.frame.width, y: 0)
}) { _ in
fromView.transform = .identity
toView.transform = .identity
transitionContext.completeTransition(true)
}
}
}
在转到的VC上设置dismiss
在ImageView上添加手势记得要加上
class DetailViewController: UIViewController {
@IBOutlet weak var detailImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
//target表示这个手势在哪里运行,actiont传入函数的固定写法
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(tap:)))
detailImageView.addGestureRecognizer(tap)
// Do any additional setup after loading the view.
}
@objc func handleTap(tap:UITapGestureRecognizer) {
dismiss(animated: true, completion: nil)
}
}