从iOS
7开始,我们通常不使用自定义序列为过渡设置动画。我们要么使用标准的模态演示,指定一个
modalTransitionStyle(即,可以为模态过渡选择的一些动画的固定列表),要么实现自定义动画过渡。这两个描述如下:
- 如果仅显示另一个视图控制器的视图,则将动画更改为翻转的简单解决方案是
modalTransitionStyle
在目标视图控制器中设置。您可以完全在segue属性下的Interface Builder中完成此 *** 作。
如果要以编程方式执行此 *** 作,则可以在目标控制器中的Swift 3中执行以下 *** 作:
override func viewDidLoad() { super.viewDidLoad() modalTransitionStyle = .flipHorizontal // use `.FlipHorizontal` in Swift 2}
然后,当您调用
show/
showViewController或
present/时
presentViewController,演示将通过水平翻转进行。而且,当您关闭视图控制器时,动画会自动为您反转。
- 如果需要更多控制,请在iOS 7及更高版本中使用自定义动画过渡,在其中指定
modalPresentationStyle
的.custom
。例如,在Swift 3中:class SecondViewController: UIViewController {let customTransitionDelegate = TransitioningDelegate()required init?(prer aDeprer: NSCoder) { super.init(prer: aDeprer) modalPresentationStyle = .custom // use `.Custom` in Swift 2 transitioningDelegate = customTransitionDelegate}...
}
这指定了
UIViewControllerTransitioningDelegate将实例化动画控制器的。例如,在Swift 3中:
class TransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return AnimationController(transitionType: .presenting) } func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return AnimationController(transitionType: .dismissing) }}
动画控制器只是做
.transitionFlipFromRight一个演示,或者
.transitionFlipFromLeft在Swift 3中关闭:
class AnimationController: NSObject, UIViewControllerAnimatedTransitioning { enum TransitionType { case presenting case dismissing } var animationTransitionOptions: UIViewAnimationOptions init(transitionType: TransitionType) { switch transitionType { case .presenting: animationTransitionOptions = .transitionFlipFromRight case .dismissing: animationTransitionOptions = .transitionFlipFromLeft } super.init() } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { //let inView = transitionContext.containerView let toView = transitionContext.viewController(forKey: .to)?.view let fromView = transitionContext.viewController(forKey: .from)?.view UIView.transition(from: fromView!, to: toView!, duration: transitionDuration(using: transitionContext), options: animationTransitionOptions.union(.curveEaseInOut)) { finished in transitionContext.completeTransition(true) } } func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 1.0 }}
有关iOS 7中引入的自定义过渡的更多信息,请参阅WWDC
2013视频使用视图控制器的自定义过渡。
- 如果应该承认上述
AnimationController
内容实际上是过分简化,因为我们正在使用transform(from:to:...)
。这样会导致动画无法取消(以防您使用交互式过渡)。它还删除了“ from”视图本身,从iOS 8开始,这实际上就是表示控制器的工作。
因此,您真的想使用
UIView.animateAPI
进行翻转动画。我很抱歉,因为以下内容涉及
CATransform3D在关键帧动画中使用一些不直观的内容,但是会导致翻转动画,然后可以对其进行可取消的交互式过渡。
因此,在Swift 3中:
class AnimationController: NSObject, UIViewControllerAnimatedTransitioning { enum TransitionType { case presenting case dismissing } let transitionType: TransitionType init(transitionType: TransitionType) { self.transitionType = transitionType super.init() } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let inView = transitionContext.containerView let toView = transitionContext.view(forKey: .to)! let fromView = transitionContext.view(forKey: .from)! var frame = inView.bounds func flipTransform(angle: CGFloat, offset: CGFloat = 0) -> CATransform3D { var transform = CATransform3DMakeTranslation(offset, 0, 0) transform.m34 = -1.0 / 1600 transform = CATransform3DRotate(transform, angle, 0, 1, 0) return transform } toView.frame = inView.bounds toView.alpha = 0 let transformFromStart: CATransform3D let transformFromEnd: CATransform3D let transformFromMiddle: CATransform3D let transformToStart: CATransform3D let transformToMiddle: CATransform3D let transformToEnd: CATransform3D switch transitionType { case .presenting: transformFromStart = flipTransform(angle: 0, offset: inView.bounds.size.width / 2) transformFromEnd = flipTransform(angle: -.pi, offset: inView.bounds.size.width / 2) transformFromMiddle = flipTransform(angle: -.pi / 2) transformToStart = flipTransform(angle: .pi, offset: -inView.bounds.size.width / 2) transformToMiddle = flipTransform(angle: .pi / 2) transformToEnd = flipTransform(angle: 0, offset: -inView.bounds.size.width / 2) toView.layer.anchorPoint = CGPoint(x: 0, y: 0.5) fromView.layer.anchorPoint = CGPoint(x: 1, y: 0.5) case .dismissing: transformFromStart = flipTransform(angle: 0, offset: -inView.bounds.size.width / 2) transformFromEnd = flipTransform(angle: .pi, offset: -inView.bounds.size.width / 2) transformFromMiddle = flipTransform(angle: .pi / 2) transformToStart = flipTransform(angle: -.pi, offset: inView.bounds.size.width / 2) transformToMiddle = flipTransform(angle: -.pi / 2) transformToEnd = flipTransform(angle: 0, offset: inView.bounds.size.width / 2) toView.layer.anchorPoint = CGPoint(x: 1, y: 0.5) fromView.layer.anchorPoint = CGPoint(x: 0, y: 0.5) } toView.layer.transform = transformToStart fromView.layer.transform = transformFromStart inView.addSubview(toView) UIView.animateKeyframes(withDuration: self.transitionDuration(using: transitionContext), delay: 0, options: [], animations: { UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.0) { toView.alpha = 0 fromView.alpha = 1 } UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5) { toView.layer.transform = transformToMiddle fromView.layer.transform = transformFromMiddle } UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.0) { toView.alpha = 1 fromView.alpha = 0 } UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5) { toView.layer.transform = transformToEnd fromView.layer.transform = transformFromEnd } }, completion: { finished in toView.layer.transform = CATransform3DIdentity fromView.layer.transform = CATransform3DIdentity toView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) fromView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) transitionContext.completeTransition(!transitionContext.transitionWasCancelled) }) } func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 1.0 }}
- 仅供参考,iOS 8通过演示控制器扩展了自定义过渡模型。有关更多信息,请参阅WWDC 2014视频A Look Inside Presentation Controllers。
无论如何,如果在过渡结束时不再可见“ from”视图,则应指示演示控制器将其从视图层次结构中删除,例如:
class PresentationController: UIPresentationController { override var shouldRemovePresentersView: Bool { return true }}
而且,显然,您必须
TransitioningDelegate将此演示控制器通知您:
class TransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate { ... func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return PresentationController(presentedViewController: presented, presenting: presenting) } }
此答案已针对Swift 3进行了更新。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)