RodolfoAntonici
RodolfoAntonici

Reputation: 1635

Custom UIViewController transition doesn't next animations perform

When I use the custom UIViewControllerAnimatedTransitioning to do a custom transition from AViewController to BViewController it performs as expected, using a Cubic Animation, but then when I try to use a default iOS presentation, like a modal to transition from BViewController to CViewController, it doesn't animate at all.

Here's the code of the first transition:

class CubeTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    private var direction: Direction!

    convenience init(direction: Direction) {
        self.init()
        self.direction = direction
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 1
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        guard let fromView = transitionContext.view(forKey: .from),
              let toView = transitionContext.view(forKey: .to) else {
                return
        }
        toView.frame = fromView.frame

        containerView.backgroundColor = UIColor.white
        let fromViewIntialTransform = fromView.layer.transform

        fromView.layer.anchorPointZ = -((fromView.frame.size.width) / 2)
        var transform: CATransform3D = CATransform3DIdentity
        transform.m34 = -1.0 / 1000
        transform = CATransform3DTranslate(transform, 0, 0, (fromView.layer.anchorPointZ))
        fromView.layer.transform = transform
        containerView.addSubview(fromView)

        toView.alpha = 1
        fromView.alpha = 1

        let toViewIntialTransform = toView.layer.transform
        toView.layer.anchorPointZ = -((toView.frame.size.width) / 2)
        transform = CATransform3DIdentity
        transform.m34 = -1.0 / 1000
        transform = CATransform3DTranslate(transform, 0, 0, (toView.layer.anchorPointZ))
        toView.layer.transform = transform

        containerView.insertSubview(toView, belowSubview:fromView)

        // transform toView to it's begining position
        switch direction {
        case .left:                                      // t                      angle                  x  y  z
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 0, 1, 0)
        case .right:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
        case .up:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi/2), 1, 0, 0)
        case .down:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 1, 0, 0)
        default:
            break
        }


        UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, options: UIViewAnimationOptions(), animations: {


            // Animate toView to go to fromView initial position,
            // And the fromView to go to a new position
            switch self.direction {
            case .left:                                      // t                      angle                  x  y  z
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
            case .right:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi / 2), 0, 1, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(-Double.pi / 2), 0, 1, 0)
            case .up:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi/2), 1, 0, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(Double.pi / 2), 1, 0, 0)
            case .down:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 1, 0, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(-Double.pi / 2), 1, 0, 0)
            default:
                break
            }
        }, completion: {(value: Bool) in
            fromView.layer.transform = fromViewIntialTransform
            toView.layer.transform = toViewIntialTransform
            fromView.layoutSubviews()
            toView.layoutSubviews()
            // This undo the transition if it's cancelled
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        })

    }



}

The thing gets even stranger when I use another transition to perform the segue from A to B, the transition from B to C starts to working again.

Second transition:

class PopTransition: NSObject, UIViewControllerAnimatedTransitioning {

    let duration = 0.3
    var originFrame = CGRect.zero
    var presenting = true

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return duration
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        let toView = transitionContext.view(forKey: .to)!
        let detailView = presenting ? toView : transitionContext.view(forKey: .from)!

        let initialFrame = presenting ? originFrame : detailView.frame
        let finalFrame = presenting ? detailView.frame : originFrame

        let xScaleFactor = presenting
            ? initialFrame.width / finalFrame.width
            : finalFrame.width / initialFrame.width

        let yScaleFactor = presenting
            ? initialFrame.height / finalFrame.height
            : finalFrame.height / initialFrame.height

        let scaleTransform = CGAffineTransform(scaleX: xScaleFactor, y: yScaleFactor)

        if presenting {
            detailView.transform = scaleTransform
            detailView.center = CGPoint(
                x: initialFrame.midX,
                y: initialFrame.midY)
        }

        containerView.addSubview(toView)
        containerView.bringSubview(toFront: detailView)

        UIView.animate(
            withDuration: duration,
            delay: 0.0,
            animations: {
                detailView.transform = self.presenting ? .identity : scaleTransform
                detailView.center = CGPoint(x: finalFrame.midX, y: finalFrame.midY)
        },
            completion:{_ in
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
        )
    }
}

Upvotes: 0

Views: 53

Answers (1)

Bocato
Bocato

Reputation: 83

You are modifying toView.layer.anchorPointZ and fromView.layer.anchorPointZ so when the transition from B to C is about to happen, the anchorPointZ is messed up.

Try saving and reseting it like you do with fromViewIntialTransform and toViewIntialTransform.

Upvotes: 1

Related Questions