iOS UIView transform doesn't scale propery while transition animetion.
Sorry for my poor English skill.
Introduction
This article shows how to solve the problem that UIView transform doesn't scale correctly while transition animation.
Transition animation make an app interactively.
But, sometimes it meka developer annoyed.
When I tried to animate a UIView scaling up and down while transition, it was not working corretly.
Conclusion
UIView transform needs to set the .identify in the completion, when it was changed in UIView animate method in transition method.
Detail
When I tried to the code below, the problem was occurred.
When new UIViewcontroller was pushed to UINavigationController, a current UIView will be scaled down while transition animation is working.
When new UIViewController was poped from UINavigationConroller, a curren UIView will be scaled up while transiotion aniomatio is working
PushAnimation
class PushModalAnimation: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 1.0 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let toViewController = transitionContext.viewController(forKey: .to), let fromViewController = transitionContext.viewController(forKey: .from) else { transitionContext.completeTransition(true) return } transitionContext.containerView.addSubview(toViewController.view) transitionContext.containerView.addSubview(fromViewController.view) UIView.animate(withDuration: 1.0, delay: 0, options: [], animations: { fromViewController.view.transform = CGAffineTransform(scaleX: 0.5, y: 0.5) }) { (_) in transitionContext.completeTransition(true) } } }
PopAnimation
class PopModalAnimation: NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 1.0 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let toViewController = transitionContext.viewController(forKey: .to), let fromViewController = transitionContext.viewController(forKey: .from) else { transitionContext.completeTransition(true) return } transitionContext.containerView.addSubview(fromViewController.view) transitionContext.containerView.addSubview(toViewController.view) UIView.animate(withDuration: 1.0, delay: 0, options: [], animations: { toViewController.view.transform = CGAffineTransform.identity }) { (_) in transitionContext.completeTransition(true) } } }
Result
Before Push new UIViewController
After Push new UIViewController
After Pop new UIViewController
After pop new UIViewController, the red UIView was bigger than its size (Befor Push new UIViewController).
Additionally, after showing this weird UIView size, tap the Home Button and came back the app. The UIView showed correctly..
How to solve the problem
After scaling down the animation in push transition, view transform need to reset the propery as .identify. Then it worked correctly.
For the solution, Before scaling down in pop transtiion, view transfrom need to set the size which was set in push transition.
The working code is below(This is part of the method.).
PushAnimation
UIView.animate(withDuration: 1.0, delay: 0, options: [], animations: { fromViewController.view.transform = CGAffineTransform(scaleX: 0.5, y: 0.5) }) { (_) in fromViewController.view.transform = CGAffineTransform.identity // Need to reset the original size transitionContext.completeTransition(true) }
PopAnimation
toViewController.view.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)// Need to set the size which was scale up from. UIView.animate(withDuration: 1.0, delay: 0, options: [], animations: { toViewController.view.transform = CGAffineTransform.identity }) { (_) in transitionContext.completeTransition(true) }
Finally
Though this problem was aimed at transform scale,I think this problem would be occurred in rotate and transition too.
But, when I change the UIView alpha proroperty in UIView animate method. It doesn't need to reset the property in completion handler.