gpt4 book ai didi

swift - Swift 中的自定义 Flip Segue

转载 作者:搜寻专家 更新时间:2023-10-30 22:22:03 25 4
gpt4 key购买 nike

这是我的自定义转场代码

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)
}
}
}

我认为这行得通,但实际上只有当转场已经执行时 View 才会改变。当“翻转”在中间时,我应该怎么做才能改变 View ?

提前致谢。

最佳答案

从 iOS 7 开始,我们通常不会使用自定义转场动画转换。我们要么使用标准模态表示,指定 modalTransitionStyle(即,我们可以为模态转换选择的一些动画的固定列表),要么实现自定义动画转换。这两个描述如下:

  1. 如果您只是展示另一个 View Controller 的 View ,将动画更改为翻转的简单解决方案是在目标 View Controller 中设置 modalTransitionStyle。您可以在 Interface Builder 中的 segue 属性下完全执行此操作。

    如果您想以编程方式执行此操作,您可以在目标 Controller 中使用 Swift 3 执行以下操作:

    override func viewDidLoad() {
    super.viewDidLoad()

    modalTransitionStyle = .flipHorizontal // use `.FlipHorizontal` in Swift 2
    }

    然后,当您调用show/showViewControllerpresent/presentViewController 时,您的演示将被执行水平翻转。而且,当您关闭 View Controller 时,动画会自动为您反转。

  2. 如果您需要更多控制,在 iOS 7 及更高版本中,您可以使用自定义动画转换,您可以在其中指定 .custommodalPresentationStyle .例如,在 Swift 3 中:

    class SecondViewController: UIViewController {

    let customTransitionDelegate = TransitioningDelegate()

    required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    modalPresentationStyle = .custom // use `.Custom` in Swift 2
    transitioningDelegate = customTransitionDelegate
    }

    ...
    }

    指定将实例化动画 Controller 的 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)
    }
    }

    动画 Controller 将简单地做 .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 .

  3. 如果应该承认上面的 AnimationController 实际上是一种过度简化,因为我们正在使用 transform(from:to:...) .这会产生不可取消的动画(如果您使用的是交互式过渡)。它还删除了“from” View 本身,从 iOS 8 开始,这实际上是呈现 Controller 的工作。

    所以,您确实想使用 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
    }
    }
  4. 仅供引用,iOS 8 使用演示 Controller 扩展了自定义转换模型。有关详细信息,请参阅 WWDC 2014 视频 A Look Inside Presentation Controllers .

    无论如何,如果在转换结束时,“from” View 不再可见,您将指示您的展示 Controller 将其从 View 层次结构中移除,例如:

    class PresentationController: UIPresentationController {
    override var shouldRemovePresentersView: Bool { return true }
    }

    而且,很明显,您必须将此表示 Controller 告知您的 TransitioningDelegate:

    class TransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {

    ...

    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
    return PresentationController(presentedViewController: presented, presenting: presenting)
    }
    }

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

关于swift - Swift 中的自定义 Flip Segue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26074979/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com