Reputation: 154
I am trying to recreate the stock UIAlertAction in a VC with a custom transition. I currently have the presenting working perfectly(backgroundView
fades in and the 'notification' VC slides from the bottom). The problem I am facing is when I dismiss the VC the backgroundView
doesn't fade out. It's as if it's completely bypassing my animation block. Once completeTransition
is called the backgroundView
disappears completely. What is happening?
class AnimationController: NSObject {
let backgroundView = UIView()
}
extension AnimationController: UIViewControllerAnimatedTransitioning {
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let toViewController = transitionContext.viewController(forKey: .to),
let fromViewController = transitionContext.viewController(forKey: .from) else {
transitionContext.completeTransition(false)
return
}
switch animationType {
case .present:
backgroundView.frame = CGRect(x: 0, y: 0, width: toViewController.view.frame.width, height: fromViewController.view.frame.height)
backgroundView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)
backgroundView.alpha = 0
containerView.addSubview(backgroundView)
let viewToAnimate = toViewController.view!
containerView.addSubview(viewToAnimate)
toViewController.view.clipsToBounds = true
viewToAnimate.frame = CGRect(x: 0, y: viewToAnimate.frame.maxY, width: viewToAnimate.frame.width, height: viewToAnimate.frame.height)
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.80, initialSpringVelocity: 0.1, options: .curveEaseInOut, animations: {
self.backgroundView.alpha = 1.0
viewToAnimate.transform = CGAffineTransform(translationX: 0, y: -viewToAnimate.frame.height)
}) { _ in
transitionContext.completeTransition(true)
}
case .dismiss:
containerView.addSubview(fromViewController.view!)
let testView = fromViewController.view!
backgroundView.frame = CGRect(x: 0, y: 0, width: testView.frame.width, height: testView.frame.height)
backgroundView.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1)
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.80, initialSpringVelocity: 0.1, options: .curveEaseInOut, animations: {
self.backgroundView.alpha = 0.0
testView.transform = CGAffineTransform(translationX: 0, y: testView.frame.height)
print("backgroundView Doesn't fade out")
}) { _ in
print("backgroundView disappears here")
transitionContext.completeTransition(true)
}
}
}
Upvotes: 3
Views: 582
Reputation: 5073
Your problem is that you're dealing with two separate instances of your AnimationController
and hence two separate instances of backgroundView
. One instance is instantiated for presentation and the other is instantiated for dismissal. Notice in your case .present:
block you are calling containerView.addSubview(backgroundView)
but you don't do the same in the case .dismiss:
block. As a result, the backgroundView
instance in the case .dismiss:
block isn't even part of the view hierarchy.
What you need to do is call self.backgroundView.removeFromSuperview()
in your first animation completion block. Then in your case .dismiss:
you need to call containerView.addSubview(backgroundView)
once again.
Try this...
switch animationType {
case .present:
// ...
containerView.addSubview(backgroundView)
// ...
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.80, initialSpringVelocity: 0.1, options: .curveEaseInOut, animations: {
self.backgroundView.alpha = 1.0
viewToAnimate.transform = CGAffineTransform(translationX: 0, y: -viewToAnimate.frame.height)
}) { _ in
self.backgroundView.removeFromSuperview()
transitionContext.completeTransition(true)
}
case .dismiss:
// ...
containerView.addSubview(backgroundView)
containerView.addSubview(fromViewController.view!)
// ...
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.80, initialSpringVelocity: 0.1, options: .curveEaseInOut, animations: {
self.backgroundView.alpha = 0.0
testView.transform = CGAffineTransform(translationX: 0, y: testView.frame.height)
print("backgroundView Doesn't fade out")
}) { _ in
print("backgroundView disappears here")
transitionContext.completeTransition(true)
}
}
Upvotes: 1
Reputation: 1448
Try This
for present replace this code
backgroundView.frame = CGRect(x: 0, y: 0, width: toViewController.view.frame.width, height: fromViewController.view.frame.height)
backgroundView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)
backgroundView.alpha = 0
containerView.addSubview(backgroundView)
let transition = CATransition()
transition.duration = 0.5
transition.type = CATransitionType.moveIn
transition.subtype = CATransitionSubtype.fromTop
containerView.layer.add(transition, forKey: kCATransition)
For Dismiss Replace this code
containerView.addSubview(fromViewController.view!)
let transition = CATransition()
transition.duration = 0.5
transition.type = CATransitionType.fade
containerView.layer.add(transition, forKey: kCATransition)
backgroundView.frame = CGRect(x: 0, y: 0, width: testView.frame.width, height: testView.frame.height)
backgroundView.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1)
self.backgroundView.alpha = 0.0
Upvotes: 0
Reputation: 347
you could try to present like this
//where DevolucionVC is you ViewController
if let controller = DevolucionVC() as? DevolucionVC {
if let window = self.window, let rootViewController = window.rootViewController {
var currentController = rootViewController
while let presentedController = currentController.presentedViewController {
currentController = presentedController
}
currentController.present(controller, animated: true, completion: nil)
}
}
you can dismiss it later by simply use
dismiss(animated: true, completion: nil)
Upvotes: 0