IOS custom transitions and rotation

I use custom transitions to display a full-screen modal representation of the game. When the user launches the game, the root view controller scales down on the screen, while the full-screen game controller scales down from the larger scale on the display when switching from 0% opacity to 100% opacity. Plain!

The transition looks great and works great, and also correctly reverses the animation when the game view controller is turned off.

The problem that I encountered is that if the device is rotated while displaying the full-screen game controller, the layout is sluggish when you return to the controller of the root view. And further rotation does not fix the problem, the layout is screwed and remains screwed.

If I disable the use of custom transitions, this problem will disappear. Also, if I save the custom transition, but disconnects the calls by setting CATransform3D in my sources and in the views in the transition animation, the problem disappears again.

Here is my transitional delegate:

class FullscreenModalTransitionManager: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate { private var presenting:Bool = true // MARK: UIViewControllerAnimatedTransitioning protocol methods func animateTransition(transitionContext: UIViewControllerContextTransitioning) { // get reference to our fromView, toView and the container view that we should perform the transition in let container = transitionContext.containerView() let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! let scale:CGFloat = 1.075 //let bigScale = CGAffineTransformMakeScale(scale, scale) //let smallScale = CGAffineTransformMakeScale(1/scale,1/scale) let bigScale = CATransform3DMakeScale(scale, scale, 1) let smallScale = CATransform3DMakeScale(1/scale, 1/scale, 1) let smallOpacity:CGFloat = 0.5 let presenting = self.presenting if presenting { // when presenting, incoming view must be on top container.addSubview(fromView) container.addSubview(toView) toView.layer.transform = bigScale toView.opaque = false toView.alpha = 0 fromView.layer.transform = CATransform3DIdentity fromView.opaque = false fromView.alpha = 1 } else { // when !presenting, outgoing view must be on top container.addSubview(toView) container.addSubview(fromView) toView.layer.transform = smallScale toView.opaque = false toView.alpha = smallOpacity fromView.layer.transform = CATransform3DIdentity fromView.opaque = false fromView.alpha = 1 } let duration = self.transitionDuration(transitionContext) UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: nil, animations: { if presenting { fromView.layer.transform = smallScale fromView.alpha = smallOpacity } else { fromView.layer.transform = bigScale fromView.alpha = 0 } }, completion: nil ) UIView.animateWithDuration(duration, delay: duration/6, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: nil, animations: { toView.layer.transform = CATransform3DIdentity toView.alpha = 1 }, completion: { finished in transitionContext.completeTransition(true) }) } func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { return 0.5 } // MARK: UIViewControllerTransitioningDelegate protocol methods func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { self.presenting = true return self } func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { self.presenting = false return self } } 

And for visual reference, what my root view controller usually looks like:

The correct layout for my root view controller

And for visual reference, what does my root view controller look like if I rotate my device (at least once) while watching a game and return to the root view controller.

Broken layout, after turning the device during full-screen viewing of the game and returning to root mode

And one final note - just in case he calls any calls - I use the auto-detection and size classes to host my root view controller.

Thanks,

+7
ios uiviewcontroller swift transitions
source share
3 answers

I accidentally realized this by doing some mock layout code for representations with non-identity transformations. It turns out that if your view has a non-identical transformation, the normal layout code does not work.

The fix in my transitional deletion was to accept the converted view, and at the end of the animation callback, it was converted to a personality (since this view is invisible at the end of the animation and behind the new view, this does not affect the appearance)

 UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: nil, animations: { if presenting { fromView.transform = smallScale fromView.alpha = smallOpacity } else { fromView.transform = bigScale fromView.alpha = 0 } }, completion: { completed in // set transform of now hidden view to identity to prevent breakage during rotation fromView.transform = CGAffineTransformIdentity }) 
+4
source share

I had a similar problem, I wrote a special transition for push and pop on the navigation controller. If you rotate the device after clicking, when you return to the root view controller, it will not change.


Problem

enter image description here


Decision

Goal c

 - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { // ViewController Reference UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; // Fix layout bug in iOS 9+ toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController]; // The rest of your code ... } 

Swift 3.0

 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { // ViewController reference let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)! // Fix layout bug in iOS 9+ toViewController.view.frame = transitionContext.finalFrame(for: toViewController) // The rest of your code ... } 
+25
source share

Finally, I found a solution to this problem. You need to improve @agilityvision code. You need to add a BOOL value, something like closeVCNow, which indicates that you want to close VC, and in animateTransition: in the animation block, do the following:

 if (self.closeVCNow) { toVC.view.transform = CGAffineTransformIdentity; toVC.view.frame = [transitionContext finalFrameForViewController:toVC]; self.closeVCNow = NO; } 
+1
source share

All Articles