Как можно реализовать кастомную анимацию перехода между двумя экранами?ios-85

В iOS кастомные переходы между экранами (UIViewController transitions) реализуются через протокол UIViewControllerAnimatedTransitioning и настройку transitionDelegate. Вот детальное объяснение:

1. Основные компоненты

Для создания кастомного перехода потребуется:

  • Объект, реализующий UIViewControllerAnimatedTransitioning
  • Установка transitioningDelegate у презентуемого контроллера
  • (Опционально) обработка жестов для интерактивных переходов

2. Реализация аниматора

Создаем класс-аниматор, который реализует протокол 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)
        }
    }
}

3. Настройка Transitioning Delegate

Создаем делегат перехода (может быть самим контроллером):

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)
    }
}

4. Инициирование перехода

При презентации контроллера устанавливаем transitioningDelegate:

let vc = SecondViewController()
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self // наш делегат
present(vc, animated: true)

5. Дополнительные возможности

Интерактивные переходы

Для создания интерактивных переходов (с жестами) нужно:

  1. Создать класс, реализующий UIPercentDrivenInteractiveTransition
  2. Добавить распознаватель жестов
  3. Обновлять прогресс анимации в обработчике жеста

Анимация через UIViewPropertyAnimator

Можно использовать современный API для более сложных анимаций:

let animator = UIViewPropertyAnimator(duration: duration, dampingRatio: 0.7) {
    // Анимационные изменения
}
animator.addCompletion { position in
    transitionContext.completeTransition(position == .end)
}
animator.startAnimation()

Советы по реализации

  1. Всегда вызывайте completeTransition() по завершении
  2. Обрабатывайте отмену перехода (transitionWasCancelled)
  3. Оптимизируйте анимации для производительности
  4. Тестируйте на разных устройствах и iOS версиях

Резюмируем:

кастомные переходы в iOS создаются через комбинацию UIViewControllerAnimatedTransitioning и transitioningDelegate, с возможностью добавления интерактивности. Это мощный инструмент для создания уникального UX в приложении.