Как унаследовать animationController от PresentationController?

Вопрос или проблема

Я пытаюсь создать переход, похожий на matchGeometry, но от представления к .sheet в Swift.

Вот хороший пример этого:

https://x.com/mlaithv/status/1835041850236838265?s=61

Виджет выбора iOS также имеет такой же переход, и это действительно круто!

Нативно это не возможно, но с помощью UIViewControllerTransitioningDelegate вы можете создать пользовательский переход к новому контроллеру представления, изменив функцию animationController делегата.

Если я использую UISheetPresentationController в качестве базового стиля представления для целевого представления (в данном случае sheet), и инициализирую его с упомянутым пользовательским делегатом перехода, я могу добиться эффекта совпадения геометрии, который я ищу, используя технику снимков, упомянутую повсюду здесь на Stack Overflow. Однако я теряю нативные жесты, интерактивность и ощущения от нативного .sheet.

Есть ли способ, как мне можно унаследовать animationController и через него жесты, взаимодействия и т. д. нативного UISheet, а затем как-то расширить/изменить его с эффектом совпадения геометрии?

Ответ или решение

Чтобы реализовать эффект перехода, подобный matchGeometry, от представления к .sheet, сохранив при этом нативные жесты и интерактивность, вам необходимо создать собственный делегат для анимации перехода, который будет переопределять метод animationController в UIViewControllerTransitioningDelegate. Однако вместо того, чтобы полностью создавать новую анимацию, мы можем попробовать наследовать существующий контроллер анимации от UISheetPresentationController и адаптировать его.

Вот пошаговое руководство по реализации:

  1. Создайте кастомный transitioning delegate:
    Вам нужно создать класс, который будет реализовывать UIViewControllerTransitioningDelegate. Этот класс будет отвечать за создание и возврат вашего аниматора.

    class CustomTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
       func animationController(forPresented presented: UIViewController, 
                                presenting: UIViewController, 
                                source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
           return MatchGeometryAnimator()
       }
    
       func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
           return MatchGeometryAnimator()
       }
    }
  2. Создайте аниматор:
    Создайте класс, который реализует UIViewControllerAnimatedTransitioning. В этом классе сконструируйте вашу кастомную анимацию, используя свойства transitionContext, чтобы получить доступ к виджетам исходного представления и целевого представления.

    class MatchGeometryAnimator: NSObject, UIViewControllerAnimatedTransitioning {
       func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
           return 0.5 // продолжительность анимации
       }
    
       func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
           // Здесь выполните свою кастомную анимацию
           let containerView = transitionContext.containerView
           let toView = transitionContext.view(forKey: .to)!
           let fromView = transitionContext.view(forKey: .from)!
    
           // Добавьте целевое представление на контейнер
           containerView.addSubview(toView)
    
           // Выполните анимацию
           toView.alpha = 0.0
           UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
               toView.alpha = 1.0
           }) { finished in
               transitionContext.completeTransition(finished)
           }
       }
    }
  3. Используйте UISheetPresentationController:
    В вашем исходном представлении инициализируйте UISheetPresentationController с вашим кастомным делегатом перехода:

    let viewControllerToPresent = YourSheetViewController()
    viewControllerToPresent.modalPresentationStyle = .custom
    let transitioningDelegate = CustomTransitioningDelegate()
    viewControllerToPresent.transitioningDelegate = transitioningDelegate
    
    // Настройка UISheetPresentationController
    if let sheet = viewControllerToPresent.sheetPresentationController {
       sheet.detents = [.medium(), .large()] 
       // Установите другие параметры по желанию
    }
    
    present(viewControllerToPresent, animated: true, completion: nil)
  4. Сохраните нативную интерактивность:
    Чтобы сохранить жесты и интерактивность, убедитесь, что ваш UISheetPresentationController отвечает за обработку жестов. Реализуйте необходимые методы, чтобы поддерживать оригинальную интерактивность, путем использования блоков анимации в вашем кастомном аниматоре.

Эта структура поможет вам достигнуть желаемого эффекта перехода с сохранением нативных жестов и интерактивности. Используя стандартные методы анимации и структурирование, вы сможете адаптировать поведение анимации, сохраняя тот опыт, к которому привыкли пользователи.

Оцените материал
Добавить комментарий

Капча загружается...