Swift中的自定义Flip Segue
这是我的自定义Segue的代码
class FlipFromRightSegue: UIStoryboardSegue { override func perform() { let source:UIViewController = self.sourceViewController as UIViewController let destination:UIViewController = self.destinationViewController as UIViewController UIView.transitionWithView(source.view,duration: 1.0,options: .CurveEaseInOut | .TransitionFlipFromRight,animations: { () -> Void in source.view.addSubview(destination.view) }) { (finished) -> Void in destination.view.removeFromSuperview() source.presentViewController(destination,animated: false,completion: nil) } } } 我认为这有效但实际上只有在已经执行segue时视图才会改变.当“翻转”位于中间时,我该怎么做才能使视图发生变化? 提前致谢.
从iOS 7开始,我们通常不使用自定义segue为转换设置动画.我们要么使用标准模态演示,指定modalTransitionStyle(即我们可以为模态过渡选择的几个动画的固定列表),要么实现自定义动画过渡.这两个描述如下:
>如果您只是呈现另一个视图控制器的视图,则将动画更改为翻转的简单解决方案是在目标视图控制器中设置modalTransitionStyle.您可以在segue的属性下完全在Interface Builder中完成此操作. 如果您想以编程方式执行此操作,则可以在目标控制器中在Swift 3中执行以下操作: override func viewDidLoad() { super.viewDidLoad() modalTransitionStyle = .flipHorizontal // use `.FlipHorizontal` in Swift 2 } 然后,当您调用show / showViewController或present / presentViewController时,您的演示文稿将以水平翻转方式执行.并且,当您关闭视图控制器时,动画会自动反转. class SecondViewController: UIViewController { let customTransitionDelegate = TransitioningDelegate() required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) 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视频Custom Transitions Using View Controllers. 所以,你真的想用UIView.animate API做翻转动画.我很抱歉,因为以下内容涉及在关键帧动画中使用一些不直观的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) transform.m34 = -1.0 / 1600 transform = CATransform3DRotate(transform,angle,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进行了更新.如果您想查看Swift 2实现,请参阅previous revision of this answer. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |