一个想要很好地展示的视图控制器的故事

曾几何时,有一个适度的视图控制器VCYellow 。 而且他既没有图片,也没有文字,甚至没有很小的业务逻辑。 他过着普通的视图控制器生活。


他的视图控制器VCMain有时将其展示给全世界:


class VCMain: UIViewController { ... @IBAction func onBtnTapMeTapped(_ sender: Any) { let vcYellow = self.storyboard!.instantiateViewController(withIdentifier: "VCYellow") as! VCYellow self.present(vcYellow, animated: true, completion: nil) } 

VCYellow则借助单个“ X”按钮躲藏起来,顺便说一句,他为之感到骄傲:


 class VCYellow: UIViewController { ... @IBAction func onBtnCloseTapped(_ sender: Any) { self.dismiss(animated: true, completion: nil) } 

它看起来还不错,但无聊又平凡:



但是我们的英雄有一个梦想,要学会表现和隐藏在美丽中。 是的,这样您就可以在假期稍后或为了保持良好的心情而改变这种美丽。



岁月流逝 ...因此,如果不是让VCYellow了解被称为:


 UIViewControllerTransitioningDelegate 

这种魔力的强大之处在于,它可以滑动适当的动画师来显示和隐藏视图控制器。 这正是我们的管制员梦about以求的。
他在古卷中阅读了如何使用该咒语,并开始进行准备。
我用咒语本身写下了一张婴儿床,以免忘记:


 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的梦想实现了! 现在,他可以根据需要显示和隐藏,没有任何东西会限制他的想象力!


可以在此处下载示例项目


我用来启发的文章在这里。

Source: https://habr.com/ru/post/zh-CN424853/


All Articles