I. Pedan
I. Pedan

Reputation: 255

How to make a copy of UIView with all layer properties?

I'm making a custom transition for presenting UINavigationController from the splash screen, and I should animate only root view controller. I have a UIStackView with buttons inside it. Every button and the UIStackView has a shadow and layer's property masksToBounds set to false. I wrote a custom animator for UINavigationController and I was doing all animations there in the method animateTransition(using transitionContext: UIViewControllerContextTransitioning). When I animate the existing UIStackView, I put it into the containerView of transitionContext and it didn't disappear when other UIViewController had been pushed. If I use removeFromSuperView, it removes from my rootViewController too. I tried to copy UIStackView like this:

let archive = NSKeyedArchiver.archivedData(withRootObject: toVC.buttonsStackView)
let buttonsStackViewCopy = NSKeyedUnarchiver.unarchiveObject(with: archive) as! UIStackView

But it doesn't copy layer's property, fonts and other.

Also I tried to render layer into ImageContext like this:

UIGraphicsBeginImageContext(toVC.buttonsStackView.bounds.size)
let context = UIGraphicsGetCurrentContext()!
toVC.buttonsStackView.layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let buttonsStackViewSnapshot = UIImageView(image: image)

The first problem was that the shadows were cut like using simple snapshot of UIView. The second problem was when I tried to increase context size. It was everything ok with shadows, but I couldn't calculate right UIImageView.frame to make right animation.

Is there any solution how to copy UIView with it's layer or how to remove it from transitionContext.containerView without removing it at all? Or may be I did everything wrong in general?

Upvotes: 2

Views: 686

Answers (1)

I. Pedan
I. Pedan

Reputation: 255

In fact it was wrong idea to copy view or it's layer. I spent two days solving this problem, but today I just added my buttonsStackView.layer as a sublayer to containerView.layer. Then, in completion closure of the animate method, I removed it from superLayer and added to my rootViewController.view.layer. It works perfectly.

transitionContext.containerView.layer.addSublayer(buttonsStackViewSnapshot)

UIView.animate(withDuration: duration,
                 animations: {
                   buttonsStackViewSnapshot.frame = finalButtonsFrame
},
                 completion: { (finished) in
                   buttonsStackViewSnapshot.removeFromSuperlayer()
                   toVC.view.layer.addSublayer(buttonsStackViewSnapshot)
                   toVC.view.isHidden = false
                   transitionContext.completeTransition(finished)
})

Upvotes: 1

Related Questions