Swift中的自定义Flip Segue

前端之家收集整理的这篇文章主要介绍了Swift中的自定义Flip Segue前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是我的自定义Segue的代码
  1. class FlipFromRightSegue: UIStoryboardSegue {
  2. override func perform() {
  3. let source:UIViewController = self.sourceViewController as UIViewController
  4. let destination:UIViewController = self.destinationViewController as UIViewController
  5.  
  6. UIView.transitionWithView(source.view,duration: 1.0,options: .CurveEaseInOut | .TransitionFlipFromRight,animations: { () -> Void in
  7. source.view.addSubview(destination.view)
  8. }) { (finished) -> Void in
  9. destination.view.removeFromSuperview()
  10. source.presentViewController(destination,animated: false,completion: nil)
  11. }
  12. }
  13. }

我认为这有效但实际上只有在已经执行segue时视图才会改变.当“翻转”位于中间时,我该怎么做才能使视图发生变化?

提前致谢.

从iOS 7开始,我们通常不使用自定义segue为转换设置动画.我们要么使用标准模态演示,指定modalTransitionStyle(即我们可以为模态过渡选择的几个动画的固定列表),要么实现自定义动画过渡.这两个描述如下:

>如果您只是呈现另一个视图控制器的视图,则将动画更改为翻转的简单解决方案是在目标视图控制器中设置modalTransitionStyle.您可以在segue的属性下完全在Interface Builder中完成此操作.

如果您想以编程方式执行此操作,则可以在目标控制器中在Swift 3中执行以下操作:

  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3.  
  4. modalTransitionStyle = .flipHorizontal // use `.FlipHorizontal` in Swift 2
  5. }

然后,当您调用show / showViewController或present / presentViewController时,您的演示文稿将以水平翻转方式执行.并且,当您关闭视图控制器时,动画会自动反转.
>如果您需要更多控制,在iOS 7及更高版本中,您将使用自定义动画过渡,您可以在其中指定.custom的modalPresentationStyle.例如,在Swift 3中:

  1. class SecondViewController: UIViewController {
  2.  
  3. let customTransitionDelegate = TransitioningDelegate()
  4.  
  5. required init?(coder aDecoder: NSCoder) {
  6. super.init(coder: aDecoder)
  7.  
  8. modalPresentationStyle = .custom // use `.Custom` in Swift 2
  9. transitioningDelegate = customTransitionDelegate
  10. }
  11.  
  12. ...
  13. }

这指定了将实例化动画控制器的UIViewControllerTransitioningDelegate.例如,在Swift 3中:

  1. class TransitioningDelegate: NSObject,UIViewControllerTransitioningDelegate {
  2. func animationController(forPresented presented: UIViewController,presenting: UIViewController,source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  3. return AnimationController(transitionType: .presenting)
  4. }
  5.  
  6. func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  7. return AnimationController(transitionType: .dismissing)
  8. }
  9. }

动画控制器只是做.transitionFlipFromRight是一个演示文稿,或者.transitionFlipFromLeft如果在Swift 3中被解雇:

  1. class AnimationController: NSObject,UIViewControllerAnimatedTransitioning {
  2.  
  3. enum TransitionType {
  4. case presenting
  5. case dismissing
  6. }
  7.  
  8. var animationTransitionOptions: UIViewAnimationOptions
  9.  
  10. init(transitionType: TransitionType) {
  11. switch transitionType {
  12. case .presenting:
  13. animationTransitionOptions = .transitionFlipFromRight
  14. case .dismissing:
  15. animationTransitionOptions = .transitionFlipFromLeft
  16. }
  17.  
  18. super.init()
  19. }
  20.  
  21. func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
  22. //let inView = transitionContext.containerView
  23. let toView = transitionContext.viewController(forKey: .to)?.view
  24. let fromView = transitionContext.viewController(forKey: .from)?.view
  25.  
  26. UIView.transition(from: fromView!,to: toView!,duration: transitionDuration(using: transitionContext),options: animationTransitionOptions.union(.curveEaseInOut)) { finished in
  27. transitionContext.completeTransition(true)
  28. }
  29. }
  30.  
  31. func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
  32. return 1.0
  33. }
  34. }

有关iOS 7中引入的自定义过渡的更多信息,请参阅WWDC 2013视频Custom Transitions Using View Controllers.
>如果应该承认上面的AnimationController实际上是一个过度简化,因为我们正在使用transform(from:to:…).这会导致动画无法取消(如果您正在使用交互式过渡).它也删除了“从”视图本身,从iOS 8开始,现在它实际上是演示控制器的工作.

所以,你真的想用UIView.animate API做翻转动画.我很抱歉,因为以下内容涉及在关键帧动画中使用一些不直观的CATransform3D,但它会产生一个翻转动画,然后可以进行可取消的交互式转换.

所以,在Swift 3中:

  1. class AnimationController: NSObject,UIViewControllerAnimatedTransitioning {
  2.  
  3. enum TransitionType {
  4. case presenting
  5. case dismissing
  6. }
  7.  
  8. let transitionType: TransitionType
  9.  
  10. init(transitionType: TransitionType) {
  11. self.transitionType = transitionType
  12.  
  13. super.init()
  14. }
  15.  
  16. func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
  17. let inView = transitionContext.containerView
  18. let toView = transitionContext.view(forKey: .to)!
  19. let fromView = transitionContext.view(forKey: .from)!
  20.  
  21. var frame = inView.bounds
  22.  
  23. func flipTransform(angle: CGFloat,offset: CGFloat = 0) -> CATransform3D {
  24. var transform = CATransform3DMakeTranslation(offset,0)
  25. transform.m34 = -1.0 / 1600
  26. transform = CATransform3DRotate(transform,angle,1,0)
  27. return transform
  28. }
  29.  
  30. toView.frame = inView.bounds
  31. toView.alpha = 0
  32.  
  33. let transformFromStart: CATransform3D
  34. let transformFromEnd: CATransform3D
  35. let transformFromMiddle: CATransform3D
  36. let transformToStart: CATransform3D
  37. let transformToMiddle: CATransform3D
  38. let transformToEnd: CATransform3D
  39.  
  40. switch transitionType {
  41. case .presenting:
  42. transformFromStart = flipTransform(angle: 0,offset: inView.bounds.size.width / 2)
  43. transformFromEnd = flipTransform(angle: -.pi,offset: inView.bounds.size.width / 2)
  44. transformFromMiddle = flipTransform(angle: -.pi / 2)
  45. transformToStart = flipTransform(angle: .pi,offset: -inView.bounds.size.width / 2)
  46. transformToMiddle = flipTransform(angle: .pi / 2)
  47. transformToEnd = flipTransform(angle: 0,offset: -inView.bounds.size.width / 2)
  48.  
  49. toView.layer.anchorPoint = CGPoint(x: 0,y: 0.5)
  50. fromView.layer.anchorPoint = CGPoint(x: 1,y: 0.5)
  51.  
  52. case .dismissing:
  53. transformFromStart = flipTransform(angle: 0,offset: -inView.bounds.size.width / 2)
  54. transformFromEnd = flipTransform(angle: .pi,offset: -inView.bounds.size.width / 2)
  55. transformFromMiddle = flipTransform(angle: .pi / 2)
  56. transformToStart = flipTransform(angle: -.pi,offset: inView.bounds.size.width / 2)
  57. transformToMiddle = flipTransform(angle: -.pi / 2)
  58. transformToEnd = flipTransform(angle: 0,offset: inView.bounds.size.width / 2)
  59.  
  60. toView.layer.anchorPoint = CGPoint(x: 1,y: 0.5)
  61. fromView.layer.anchorPoint = CGPoint(x: 0,y: 0.5)
  62. }
  63.  
  64. toView.layer.transform = transformToStart
  65. fromView.layer.transform = transformFromStart
  66. inView.addSubview(toView)
  67.  
  68. UIView.animateKeyframes(withDuration: self.transitionDuration(using: transitionContext),delay: 0,options: [],animations: {
  69. UIView.addKeyframe(withRelativeStartTime: 0,relativeDuration: 0.0) {
  70. toView.alpha = 0
  71. fromView.alpha = 1
  72. }
  73. UIView.addKeyframe(withRelativeStartTime: 0,relativeDuration: 0.5) {
  74. toView.layer.transform = transformToMiddle
  75. fromView.layer.transform = transformFromMiddle
  76. }
  77. UIView.addKeyframe(withRelativeStartTime: 0.5,relativeDuration: 0.0) {
  78. toView.alpha = 1
  79. fromView.alpha = 0
  80. }
  81. UIView.addKeyframe(withRelativeStartTime: 0.5,relativeDuration: 0.5) {
  82. toView.layer.transform = transformToEnd
  83. fromView.layer.transform = transformFromEnd
  84. }
  85. },completion: { finished in
  86. toView.layer.transform = CATransform3DIdentity
  87. fromView.layer.transform = CATransform3DIdentity
  88. toView.layer.anchorPoint = CGPoint(x: 0.5,y: 0.5)
  89. fromView.layer.anchorPoint = CGPoint(x: 0.5,y: 0.5)
  90.  
  91. transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
  92. })
  93. }
  94.  
  95. func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
  96. return 1.0
  97. }
  98. }

>仅供参考,iOS 8通过演示控制器扩展了自定义转换模型.有关更多信息,请参阅WWDC 2014视频A Look Inside Presentation Controllers.

无论如何,如果在转换结束时,“from”视图不再可见,您将指示您的演示控制器将其从视图层次结构中删除,例如:

  1. class PresentationController: UIPresentationController {
  2. override var shouldRemovePresentersView: Bool { return true }
  3. }

显然,你必须通知你的TransitioningDelegate这个演示控制器:

  1. class TransitioningDelegate: NSObject,UIViewControllerTransitioningDelegate {
  2.  
  3. ...
  4.  
  5. func presentationController(forPresented presented: UIViewController,presenting: UIViewController?,source: UIViewController) -> UIPresentationController? {
  6. return PresentationController(presentedViewController: presented,presenting: presenting)
  7. }
  8. }

此答案已针对Swift 3进行了更新.如果您想查看Swift 2实现,请参阅previous revision of this answer.

猜你在找的Swift相关文章