Swift中的自定义翻转Segue

Swift中的自定义翻转Segue,第1张

Swift中的自定义翻转Segue

从iOS
7开始,我们通常不使用自定义序列为过渡设置动画。我们要么使用标准的模态演示,指定一个

modalTransitionStyle
(即,可以为模态过渡选择的一些动画的固定列表),要么实现自定义动画过渡。这两个描述如下:

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

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

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

然后,当您调用

show
/
showViewController
present
/时
presentViewController
,演示将通过水平翻转进行。而且,当您关闭视图控制器时,动画会自动为您反转。

  1. 如果需要更多控制,请在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视频使用视图控制器的自定义过渡。

  1. 如果应该承认上述
    AnimationController
    内容实际上是过分简化,因为我们正在使用
    transform(from:to:...)
    。这样会导致动画无法取消(以防您使用交互式过渡)。它还删除了“ from”视图本身,从iOS 8开始,这实际上就是表示控制器的工作。

因此,您真的想使用

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, 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    }}
  1. 仅供参考,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进行了更新。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5662515.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存