Информационный портал по безопасности » Программирование » Веб-разработка » История одного вью-контроллера, который хотел показываться красиво

 

История одного вью-контроллера, который хотел показываться красиво

Автор: admin от 30-09-2018, 04:50, посмотрело: 148

Жил был скромный вью-контроллер VCYellow. И не было у него ни картинки, ни текста, ни даже малюсенькой бизнес логики. Жил он обычной вью-контроллерской жизнью.

древних свитках как использовать заклятие и начал готовиться.

Записал себе шпаргалку с самим заклинанием, чтобы не забыть:



extension VCYellow: UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController)  UIViewControllerAnimatedTransitioning? {
        return AnimatorPresent(startFrame: self.startFrame)
    }

    func animationController(forDismissed dismissed: UIViewController)  UIViewControllerAnimatedTransitioning? {
        return AnimatorDismiss(endFrame: self.startFrame)
    }
}

В ней он тщательно расписал, что для показа нужно использовать аниматор AnimatorPresent, а при закрытии AnimatorDismiss.
Ну и в качестве помощи обоим аниматорам было решено передать фрейм главной кнопки из VCMain


А потом и сам морально настроился. Потому как без правильного настроя, как известно, никакая магия не работает:


override func viewDidLoad() {
    super.viewDidLoad()
    self.modalPresentationStyle = .custom
    self.transitioningDelegate = self
}

Попросил он своего друга VCMain презентануть себя, чтобы проверить как магия сработает и… сработала она никак…
Оказалось, что AnimatorPresent и AnimatorDismiss сами собой не появляются.


Останавливаться было уже поздно и наш герой решил создать необходимые аниматоры. Поковырялся в нужном разделе древних свитков и узнал, что для создания аниматора достаточно двух вещей.


Во-первых надо задать время, отведённое для анимации:


func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?)  TimeInterval {
    return 0.3
}

а во-вторых обозначить саму анимацию:



func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    //1
    guard let vcTo = transitionContext.viewController(forKey: .to),
        let snapshot = vcTo.view.snapshotView(afterScreenUpdates: true) else {
        return
    }

    //2
    let vContainer = transitionContext.containerView

    //3
    vcTo.view.isHidden = true
    vContainer.addSubview(vcTo.view)

    //4
    snapshot.frame = self.startFrame
    vContainer.addSubview(snapshot)

    UIView.animate(withDuration: 0.3, animations: {
        //5
        snapshot.frame = (transitionContext.finalFrame(for: vcTo))
    }, completion: { success in
        //6
        vcTo.view.isHidden = false
        snapshot.removeFromSuperview()
        transitionContext.completeTransition(true)
    })
}


  1. Вытащить презентуемый вью-контроллер(в нашем случае VCYellow) и сфоткать его. Фотка нужна для упрощения анимации.

  2. Получить вьюшку, на которой будет происходить анимационное колдунство. Назовем её контекст.

  3. Нацепить вьюху конечного контроллера на контекст и скрыть её. Показать

  4. её было решено после того как закончится анимация.

  5. Подготовить фотку для анимации. Уменьшить до начальных размеров и кинуть на контекст.

  6. Расщеперить фотку на весь экран, тем самым анимировав процесс презентации.

  7. После окончания анимации показать настоящую вьюху конечного контроллера,

  8. избавиться от фотки и сообщить, что действо окончено.


В результате вышел вот такой аниматор для показа:


import UIKit

class AnimatorPresent: NSObject, UIViewControllerAnimatedTransitioning {
    let startFrame: CGRect

    init(startFrame: CGRect) {
        self.startFrame = startFrame
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?)  TimeInterval {
        return 0.3
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let vcTo = transitionContext.viewController(forKey: .to),
        let snapshot = vcTo.view.snapshotView(afterScreenUpdates: true) else {
            return
        }

        let vContainer = transitionContext.containerView

        vcTo.view.isHidden = true
        vContainer.addSubview(vcTo.view)

        snapshot.frame = self.startFrame
        vContainer.addSubview(snapshot)

        UIView.animate(withDuration: 0.3, animations: {
            snapshot.frame = (transitionContext.finalFrame(for: vcTo))
        }, completion: { success in
            vcTo.view.isHidden = false
            snapshot.removeFromSuperview()
            transitionContext.completeTransition(true)
        })
    }
}

А после этого несложно было написать аниматор для скрывания, который делает примерно то же самое, но наоборот:


import UIKit

class AnimatorDismiss: NSObject, UIViewControllerAnimatedTransitioning {

    let endFrame: CGRect

    init(endFrame: CGRect) {
        self.endFrame = endFrame
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?)  TimeInterval {
        return 0.3
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let vcTo = transitionContext.viewController(forKey: .to),
        let vcFrom = transitionContext.viewController(forKey: .from),
        let snapshot = vcFrom.view.snapshotView(afterScreenUpdates: true) else {
            return
        }

        let vContainer = transitionContext.containerView
        vContainer.addSubview(vcTo.view)
        vContainer.addSubview(snapshot)

        vcFrom.view.isHidden = true

        UIView.animate(withDuration: 0.3, animations: {
            snapshot.frame = self.endFrame
        }, completion: { success in
            transitionContext.completeTransition(true)
        })
    }
}


Закончив все доделки, VCYellow опять попросил своего друга VCMain презентовать себя и о чудо!



История одного вью-контроллера, который хотел показываться красиво



Магия сработала! Мечта VCYellow сбылась! Теперь он может показываться и скрываться как ему захочется и ничто не будет ограничивать его фантазию!



Проект-пример можно скачать тут



Статья, которую я использовал для вдохновения находится тут



Источник: Хабр / Интересные публикации

Категория: Веб-разработка / iOS

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
  • bowtiesmilelaughingblushsmileyrelaxedsmirk
    heart_eyeskissing_heartkissing_closed_eyesflushedrelievedsatisfiedgrin
    winkstuck_out_tongue_winking_eyestuck_out_tongue_closed_eyesgrinningkissingstuck_out_tonguesleeping
    worriedfrowninganguishedopen_mouthgrimacingconfusedhushed
    expressionlessunamusedsweat_smilesweatdisappointed_relievedwearypensive
    disappointedconfoundedfearfulcold_sweatperseverecrysob
    joyastonishedscreamtired_faceangryragetriumph
    sleepyyummasksunglassesdizzy_faceimpsmiling_imp
    neutral_faceno_mouthinnocent