第一种:没有动画效果跳转
效果图:
无动画效果.gif
从 AViewController -> BViewController
@objc func toBViewController() {
let bVC = BViewController()
// 注意:设置目标控制器 transition 转场效果代理. self: AViewController
bVC.transitioningDelegate = self
self.present(bVC, animated: true, completion: nil)
}
// MARK: - UIViewControllerTransitioningDelegate
extension HomeViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
}
// MARK: - UIViewControllerAnimatedTransitioning 关于取消 present 效果跳转(无动画效果)
extension HomeViewController: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.5
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// 关于取消 present 效果跳转(无动画效果)
guard let toView = transitionContext.view(forKey: .to) else {
transitionContext.completeTransition(true)
return
}
transitionContext.containerView.addSubview(toView)
transitionContext.completeTransition(true)
}
}
第二种:类似 push、pop动画效果跳转
效果图:
类似 push/pop效果.gif
从 AViewController -> BViewController
enum TransitionType {
case present
case dismiss
}
@objc func toBViewController() {
let bVC = BViewController()
// 注意:设置目标控制器 transition 转场效果代理. self: AViewController
bVC.transitioningDelegate = self
self.present(bVC, animated: true, completion: nil)
}
// MARK: - UIViewControllerTransitioningDelegate
extension HomeViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.type = .present
return self
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.type = .dismiss
return self
}
}
// MARK: - UIViewControllerAnimatedTransitioning 关于自定义转场动效(push / pop 效果,push:从右->左;pop:从左->右)
extension HomeViewController: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.5
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let toView = transitionContext.view(forKey: .to),
let fromView = transitionContext.view(forKey: .from) else {
transitionContext.completeTransition(true)
return
}
// 呈现在当前屏幕上的 vc 则为 from;目标 vc 则为to
switch self.type {
case .present:
transitionContext.containerView.addSubview(toView)
toView.transform = CGAffineTransform(translationX: self.view.bounds.width, y: 0)
UIView.animate(withDuration: transitionDuration(using: nil)) {
toView.transform = .identity
} completion: { _ in
transitionContext.completeTransition(true)
}
case .dismiss:
// 将 toView 放置最底层,fromView平移后,就会看到 toview;如果直接 add toView,则效果会一闪,看不到 fromView 平移效果。原因:add toView 后被 toView 遮住了。
// 因此使用 insertSubview
transitionContext.containerView.insertSubview(toView, at: 0)
UIView.animate(withDuration: transitionDuration(using: nil)) {
fromView.transform = CGAffineTransform(translationX: self.view.bounds.width, y: 0)
} completion: { _ in
transitionContext.completeTransition(true)
}
}
}
}
第三种:类似 淘宝展示商品 动画效果跳转
效果图:
商品.gif
@objc func toBViewController() {
let bVC = BViewController()
// 注意:设置目标控制器 transition 转场效果代理. self: AViewController
bVC.transitioningDelegate = self
bVC.view.frame = CGRect(x: 0, y: self.view.bounds.height - detailViewHeight, width: self.view.bounds.width, height: detailViewHeight)
self.present(bVC, animated: true, completion: nil)
}
@objc func tapFromView() {
self.dismiss(animated: true, completion: nil)
}
// MARK: - UIViewControllerTransitioningDelegate
extension HomeViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.type = .present
return self
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.type = .dismiss
return self
}
}
// MARK: - UIViewControllerAnimatedTransitioning 关于淘宝展示商品信息效果转场效果
extension HomeViewController: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// 关于取消 present 效果跳转(无动画效果)
guard let toView = transitionContext.view(forKey: .to),
let fromView = transitionContext.view(forKey: .from) else {
transitionContext.completeTransition(true)
return
}
switch self.type {
case .present:
transitionContext.containerView.addSubview(toView)
// 设置商品 VC 效果
var transition3D = CATransform3DIdentity
// CATransform3D 的 m34 元素,用来做透视(有 3D 效果);
// m34 为-1.0 / d 来应用透视效果; d = 通常500~1000
// 注意:得先设置
transition3D.m34 = -1 / 1000
// 绕 x 轴3D旋转 pi/5
transition3D = CATransform3DRotate(transition3D, .pi / 8, 1, 0, 0)
// 防止 fromView 旋转后遮住 toView; fromView平移(z轴方向)
transition3D = CATransform3DTranslate(transition3D, 0, 0, -200)
UIView.animate(withDuration: transitionDuration(using: nil)) {
fromView.layer.transform = transition3D
} completion: { _ in
// 再进行缩放
UIView.animate(withDuration: self.transitionDuration(using: nil)) {
fromView.layer.transform = CATransform3DMakeScale(0.9, 0.9, 1)
}
}
// toView 动画
toView.transform = CGAffineTransform(translationX: 0, y: toView.bounds.height)
UIView.animate(withDuration: transitionDuration(using: nil)*2) {
toView.transform = .identity
} completion: { _ in
// 由于 completeTransition 后会出现 fromView 被移除,因此需要截图 代替 fromView
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0)
// 截取当前屏幕
self.view.drawHierarchy(in: self.view.bounds, afterScreenUpdates: false)
// 截取的当前UIView转成UIImage
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let replaceImageView = UIImageView(image: image)
replaceImageView.isUserInteractionEnabled = true
replaceImageView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
let tap = UITapGestureRecognizer(target: self, action: #selector(self.tapFromView))
replaceImageView.addGestureRecognizer(tap)
transitionContext.containerView.insertSubview(replaceImageView, at: 0)
transitionContext.completeTransition(true)
}
case .dismiss:
transitionContext.containerView.addSubview(fromView)
UIView.animate(withDuration: transitionDuration(using: nil)) {
fromView.transform = CGAffineTransform(translationX: 0, y: fromView.bounds.height)
} completion: { _ in
UIView.animate(withDuration: self.transitionDuration(using: nil)*0.5) {
toView.transform = .identity
}
transitionContext.completeTransition(true)
}
}
}
}
网友评论