跳到主要内容

转场动画

问题

iOS 自定义转场动画的实现方式?

答案

UIKit 自定义转场

// 1. 实现 UIViewControllerAnimatedTransitioning
class FadeTransition: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using context: UIViewControllerContextTransitionContext?) -> TimeInterval {
return 0.3
}

func animateTransition(using context: UIViewControllerContextTransitionContext) {
guard let toView = context.view(forKey: .to) else { return }
let container = context.containerView
toView.alpha = 0
container.addSubview(toView)

UIView.animate(withDuration: 0.3) {
toView.alpha = 1
} completion: { _ in
context.completeTransition(!context.transitionWasCancelled)
}
}
}

// 2. 设置代理
class ViewController: UIViewController, UIViewControllerTransitioningDelegate {
func presentDetail() {
let vc = DetailVC()
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self
present(vc, animated: true)
}

func animationController(forPresented presented: UIViewController,
presenting: UIViewController,
source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return FadeTransition()
}
}

SwiftUI 转场

struct ContentView: View {
@State private var showDetail = false

var body: some View {
VStack {
if showDetail {
DetailView()
.transition(.asymmetric(
insertion: .scale.combined(with: .opacity),
removal: .slide
))
}
}
.animation(.spring(), value: showDetail)
}
}

// iOS 18+ matchedTransitionSource
// 共享元素转场

常见面试问题

Q1: 交互式转场怎么实现?

答案:使用 UIPercentDrivenInteractiveTransition,配合 UIPanGestureRecognizer,根据手势进度调用 update(_:)finish()cancel() 控制转场进度。iOS 侧滑返回就是这个原理。

相关链接