В iOS кастомные переходы между экранами (UIViewController transitions) реализуются через протокол UIViewControllerAnimatedTransitioning
и настройку transitionDelegate
. Вот детальное объяснение:
Для создания кастомного перехода потребуется:
UIViewControllerAnimatedTransitioning
transitioningDelegate
у презентуемого контроллераСоздаем класс-аниматор, который реализует протокол UIViewControllerAnimatedTransitioning
:
class CustomTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
let duration: TimeInterval
var isPresenting: Bool
init(duration: TimeInterval = 0.5, isPresenting: Bool = true) {
self.duration = duration
self.isPresenting = isPresenting
}
// Длительность анимации
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
// Сама анимация
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromVC = transitionContext.viewController(forKey: .from),
let toVC = transitionContext.viewController(forKey: .to) else {
transitionContext.completeTransition(false)
return
}
let containerView = transitionContext.containerView
let finalFrame = transitionContext.finalFrame(for: toVC)
if isPresenting {
// Начальное состояние для презентации
toVC.view.frame = finalFrame.offsetBy(dx: 0, dy: finalFrame.height)
containerView.addSubview(toVC.view)
} else {
// Начальное состояние для dismiss
containerView.insertSubview(toVC.view, belowSubview: fromVC.view)
}
UIView.animate(withDuration: duration, animations: {
if self.isPresenting {
toVC.view.frame = finalFrame
} else {
fromVC.view.frame = finalFrame.offsetBy(dx: 0, dy: finalFrame.height)
}
}) { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
Создаем делегат перехода (может быть самим контроллером):
extension ViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController,
presenting: UIViewController,
source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return CustomTransitionAnimator(isPresenting: true)
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return CustomTransitionAnimator(isPresenting: false)
}
}
При презентации контроллера устанавливаем transitioningDelegate:
let vc = SecondViewController()
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self // наш делегат
present(vc, animated: true)
Для создания интерактивных переходов (с жестами) нужно:
UIPercentDrivenInteractiveTransition
Можно использовать современный API для более сложных анимаций:
let animator = UIViewPropertyAnimator(duration: duration, dampingRatio: 0.7) {
// Анимационные изменения
}
animator.addCompletion { position in
transitionContext.completeTransition(position == .end)
}
animator.startAnimation()
completeTransition()
по завершении кастомные переходы в iOS создаются через комбинацию UIViewControllerAnimatedTransitioning
и transitioningDelegate
, с возможностью добавления интерактивности. Это мощный инструмент для создания уникального UX в приложении.