I would like a SwiftUI slide transition effect in which the current UIView slides out and next UIView slides in, but the current UIView simply disappears and then the next view slides in, couldn’t find out the reason, I’m using Xcode 14.2 for iOS 16.2.
class SlideTransition: NSObject, UIViewControllerAnimatedTransitioning {
enum Direction {
case left, right
}
let duration: TimeInterval
let direction: Direction
init(duration: TimeInterval = 1, direction: Direction = .left) {
self.duration = duration
self.direction = direction
super.init()
}
@objc func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
@objc func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard
let fromView = transitionContext.view(forKey: .from),
let toView = transitionContext.view(forKey: .to)
else {
transitionContext.completeTransition(false)
return
}
let containerView = transitionContext.containerView
let containerBounds = containerView.bounds
let fromViewEndFrame: CGRect
let toViewStartFrame: CGRect
// Determine the slide direction
switch direction {
case .left:
fromViewEndFrame = containerBounds.offsetBy(dx: -containerBounds.width, dy: 0)
toViewStartFrame = containerBounds.offsetBy(dx: containerBounds.width, dy: 0)
case .right:
fromViewEndFrame = containerBounds.offsetBy(dx: containerBounds.width, dy: 0)
toViewStartFrame = containerBounds.offsetBy(dx: -containerBounds.width, dy: 0)
}
toView.frame = toViewStartFrame
containerView.addSubview(toView)
// UIView.animate(withDuration: duration, animations: {
// // Slide out the fromView and slide in the toView
// fromView.frame = fromViewEndFrame
// toView.frame = containerBounds
// }, completion: { finished in
// let wasCancelled = transitionContext.transitionWasCancelled
// transitionContext.completeTransition(!wasCancelled)
//
// // If the transition was cancelled, remove the toView to avoid a broken state
// if wasCancelled {
// toView.removeFromSuperview()
// }
// })
// Perform the animation
let animator = UIViewPropertyAnimator(duration: transitionDuration(using: transitionContext), curve: .easeInOut) {
// Animate both views simultaneously
fromView.frame = fromViewEndFrame
toView.frame = containerBounds
}
// Add a completion block to handle the end of the animation
animator.addCompletion { finished in
let wasCancelled = transitionContext.transitionWasCancelled
transitionContext.completeTransition(!wasCancelled)
// If the transition was canceled, reset the toView's frame to its initial position
if wasCancelled {
toView.removeFromSuperview()
}
}
animator.startAnimation()
}
}
both UIView.animate and UIViewPropertyAnimator have the same results, the current view simply disappears instead of sliding out.
And I tried the HeroTransition library, the transition worked, but unable to set the transition duration.
could someone help? thanks 🙂