I'm trying to make a slide animation for my navigation controller transitions. For instance, when I push a VC, the presenting and the presented VCs will transition just like a UIPageViewController
transition.
Here is what I've coded so far:
guard let fromView = transitionContext.view(forKey: .from),
let toView = transitionContext.view(forKey: .to)
else { return }
let containerView = transitionContext.containerView
toView.frame = CGRect(x: -toViewFrameHorizationtalPosition,
y: 64,
width: UIScreen.main.bounds.width,
height: UIScreen.main.bounds.height)
containerView.addSubview(fromView)
containerView.addSubview(toView)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: .curveEaseInOut,
animations: {
containerView.frame.origin.x = self.toViewFrameHorizationtalPosition
}) { completed in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
The transition animation is happening as I expected it to be but even though against various tries, once the animation executes the view becomes unresponsive; it does not recognise any touch events.
The navigation bar works fine but when I switch back to the initial view, that view is unresponsive as well.
I've read a lot on this and been struggling with this for a while now although I can't seem to spot the issue. Any ideas?
Alright then, I finally found the solution. Many many thanks to @DonMag for pointing me in the right direction with his great comment!
First off, as @DonMag has also mentioned, it was needless of me to add the fromView
into the containerView
as it's already present inside there.
Anyways, the problem with the presented view, toView
, being unresponsive was that for the purposes of making the slide animation:
toView
s frame origin to position it right inside the container view,fromView
and the toView
to act one next to the other, i.e. just like how a UIPageViewController animates.The problem was that I was not setting them back to their original values. Once I set toView
s and containerView
s frame origins back to their original values in the animation completion block, everything worked as expected.
Here is the revised animation code:
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let toView = transitionContext.view(forKey: .to)
else { return }
toView.removeFromSuperview()
toView.frame = CGRect(x: -toViewFrameHorizationtalPosition,
y: 64,
width: UIScreen.main.bounds.width,
height: UIScreen.main.bounds.height)
let containerView = transitionContext.containerView
containerView.addSubview(toView)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: .curveEaseInOut,
animations: {
containerView.frame.origin.x = self.toViewFrameHorizationtalPosition
}) { completed in
containerView.frame.origin.x = 0
toView.frame.origin.x = 0
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
P.S. Again, many many thanks to @DonMag. Your insight has been really helpful.