Flip view like UIView.transition with Core Animation - ios

I want to create a transition between two views like UIView.transition with .transitionFlipFromLeft. For example:
import UIKit
class ViewController: UIViewController {
static let frame = CGRect(x: 0, y: 0, width: 300, height: 200)
let viewContainer = UIView(frame: frame)
let view1 = UIView(frame: frame)
let view2 = UIView(frame: frame)
var currentView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.view1.backgroundColor = .blue
self.view2.backgroundColor = .red
self.currentView = self.view1
self.view.addSubview(self.viewContainer)
self.viewContainer.addSubview(self.currentView)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if currentView == view1 {
flip(to: view2)
} else {
flip(to: view1)
}
}
func flip(to toView: UIView) {
UIView.transition(from: currentView,
to: toView,
duration: 1,
options: .transitionFlipFromLeft,
completion: { _ in self.currentView = toView })
}
}
It should be possible to reach a similar effect by using Core Animation. I replaced UIView.transition in func flip(to toView: UIView):
func flip(to toView: UIView) {
var transform = CATransform3DIdentity
transform.m34 = -1 / 400
toView.layer.transform = transform
self.currentView.layer.transform = transform
let disappearByRotating = CABasicAnimation(keyPath: "transform.rotation.y")
disappearByRotating.duration = 0.5
disappearByRotating.fromValue = 0
disappearByRotating.toValue = CGFloat.pi / 2
let appearByRotating = CABasicAnimation(keyPath: "transform.rotation.y")
appearByRotating.duration = 0.5
appearByRotating.fromValue = CGFloat.pi / 2
appearByRotating.toValue = CGFloat.pi
CATransaction.begin()
CATransaction.setCompletionBlock {
self.currentView.removeFromSuperview()
self.viewContainer.addSubview(toView) // <= Problem!
toView.layer.add(appearByRotating, forKey: "appear")
self.currentView = toView
}
self.currentView.layer.add(disappearByRotating, forKey: "disappear")
CATransaction.commit()
}
I used two animations: In the first animation, the first view rotates from the left to the middle, in the second animation, the second view rotates from the middle to the right.
When I add the second view to my viewContainer, it is displayed untransformed before the second animation starts. This causes flickering:
How can I prevent the flickering?

One option:
apply a 90-degree rotation to toView.layer before anything else
toView will now be "invisible" so add it as a subview
embed a new CATransaction with new Completion Block in the original Completion Block to "remove" the transform from toView.layer
Try this:
func flip(to toView: UIView) {
var transform = CATransform3DIdentity
transform.m34 = -1 / 400
// start toView rotated 90 degrees
transform = CATransform3DRotate(transform, CGFloat.pi / 2, 0, 1, 0)
toView.layer.transform = transform
// because toView's layer is rotated 90 degrees, we can
// add the subview here and it won't be visible
// really no difference between .addSubview and .insertSubview for our purposes
// but we'll insert it under the current view anyway
self.viewContainer.insertSubview(toView, belowSubview: self.currentView)
transform = CATransform3DIdentity
transform.m34 = -1 / 400
self.currentView.layer.transform = transform
let disappearByRotating = CABasicAnimation(keyPath: "transform.rotation.y")
disappearByRotating.duration = 0.5
disappearByRotating.fromValue = 0
disappearByRotating.toValue = CGFloat.pi / 2
disappearByRotating.fillMode = .forwards
disappearByRotating.isRemovedOnCompletion = false
let appearByRotating = CABasicAnimation(keyPath: "transform.rotation.y")
appearByRotating.duration = 0.5
appearByRotating.fromValue = -CGFloat.pi / 2
appearByRotating.toValue = 0
appearByRotating.fillMode = .forwards
appearByRotating.isRemovedOnCompletion = false
CATransaction.begin()
CATransaction.setCompletionBlock {
self.currentView.removeFromSuperview()
// start a new CATransaction with new Completion Block
CATransaction.begin()
CATransaction.setCompletionBlock {
self.currentView.layer.removeAnimation(forKey: "disappear")
toView.layer.removeAnimation(forKey: "appear")
// remove 90-degree-rotation starting point from toView
toView.layer.transform = CATransform3DIdentity
self.currentView = toView
}
toView.layer.add(appearByRotating, forKey: "appear")
CATransaction.commit()
}
self.currentView.layer.add(disappearByRotating, forKey: "disappear")
CATransaction.commit()
}

Related

CALayer Presentation nil

I am trying to use a CABasicAnimation for the timing function with custom objects (not UIView).
I'm trying to implement #CIFilter's answer from here which is to use the CALayer's presentation layer that is animated to evaluate the timing function.
I'm doing it all in viewDidAppear, so a valid view exists, but no matter what I do, the Presentation layer is always nil.
Note that I have to add the animation to the view's layer and not the layer I've added to it for it to animate at all. And if I uncomment the lines commented out below I can see that the animation works (but only when animating the root layer). Regardless, the Presentation layer is nil.
I've looked at dozen's of tutorials and SO answers, and it seems this should just work, so I suppose I must be doing something stupid.
I am just trying to use the CoreAnimation timing functions. I have UICubicTimingParameters working, but seems like going the CA route offers much more functionality which would be nice.
import UIKit
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let newView = UIView(frame: view.frame)
view.addSubview(newView)
let evaluatorLayer = CALayer()
evaluatorLayer.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
evaluatorLayer.borderWidth = 8.0
evaluatorLayer.borderColor = UIColor.purple.cgColor
evaluatorLayer.timeOffset = 0.3
evaluatorLayer.isHidden = true
// evaluatorLayer.isHidden = false
newView.layer.addSublayer(evaluatorLayer)
let basicAnimation = CABasicAnimation(keyPath: "bounds.origin.x")
basicAnimation.duration = 1.0
basicAnimation.fromValue = 0.0
basicAnimation.toValue = 100.0
basicAnimation.fillMode = .forwards
basicAnimation.isRemovedOnCompletion = false
basicAnimation.speed = 0.0
// basicAnimation.speed = 0.1
newView.layer.add(basicAnimation, forKey: "evaluate")
if let presentationLayer = newView.layer.presentation() {
let evaluatedValue = presentationLayer.bounds.origin.x
print("evaluatedValue: \(evaluatedValue)")
}
else {
print(evaluatorLayer.presentation())
}
}
}
Not sure if your code is going to do what you expect, but...
I think the reason .presentation() is nil is because you haven't given UIKit an opportunity to apply the animation.
Try this:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let newView = UIView(frame: view.frame)
view.addSubview(newView)
let evaluatorLayer = CALayer()
evaluatorLayer.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
evaluatorLayer.borderWidth = 8.0
evaluatorLayer.borderColor = UIColor.purple.cgColor
evaluatorLayer.timeOffset = 0.3
evaluatorLayer.isHidden = true
// evaluatorLayer.isHidden = false
newView.layer.addSublayer(evaluatorLayer)
let basicAnimation = CABasicAnimation(keyPath: "bounds.origin.x")
basicAnimation.duration = 1.0
basicAnimation.fromValue = 0.0
basicAnimation.toValue = 100.0
basicAnimation.fillMode = .forwards
basicAnimation.isRemovedOnCompletion = false
basicAnimation.speed = 0.0
// basicAnimation.speed = 0.1
newView.layer.add(basicAnimation, forKey: "evaluate")
DispatchQueue.main.async {
if let presentationLayer = newView.layer.presentation() {
let evaluatedValue = presentationLayer.bounds.origin.x
print("async evaluatedValue: \(evaluatedValue)")
}
else {
print("async", evaluatorLayer.presentation())
}
}
if let presentationLayer = newView.layer.presentation() {
let evaluatedValue = presentationLayer.bounds.origin.x
print("immediate evaluatedValue: \(evaluatedValue)")
}
else {
print("immediate", evaluatorLayer.presentation())
}
}
My debug output is:
immediate nil
async evaluatedValue: 0.0
Edit
I'm still not sure what your goal is, but give this a try...
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let newView = UIView(frame: view.frame)
view.addSubview(newView)
let evaluatorLayer = CALayer()
evaluatorLayer.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
evaluatorLayer.borderWidth = 8.0
evaluatorLayer.borderColor = UIColor.purple.cgColor
evaluatorLayer.isHidden = true
//evaluatorLayer.isHidden = false
newView.layer.addSublayer(evaluatorLayer)
let basicAnimation = CABasicAnimation(keyPath: "bounds.origin.x")
basicAnimation.duration = 1.0
basicAnimation.fromValue = 0.0
basicAnimation.toValue = 100.0
basicAnimation.fillMode = .forwards
basicAnimation.isRemovedOnCompletion = false
basicAnimation.speed = 0.0
//basicAnimation.speed = 1.0
// set timeOffset on the animation, not on the layer itself
basicAnimation.timeOffset = 0.3
// add animation to evaluatorLayer
evaluatorLayer.add(basicAnimation, forKey: "evaluate")
DispatchQueue.main.async {
// get presentation layer of evaluatorLayer
if let presentationLayer = evaluatorLayer.presentation() {
let evaluatedValue = presentationLayer.bounds.origin.x
print("async evaluatedValue: \(evaluatedValue)")
}
else {
print("async", evaluatorLayer.presentation())
}
}
}
In this example, we apply the .timeOffset on the animation, not on the layer. And, we add the animation to the evaluatorLayer, not to the newView.layer.
Output (for my quick test):
async evaluatedValue: 30.000001192092896

Custom ViewController Transition always starts from the center

I'm trying to create a custom ViewController transition.
I'm basically trying to replicate Apple's animation when launching an app, the zoom in starts from the application's position.
I have a collection view, and when the user taps on a cell, I get the cell's point (which does work), and I'm trying to set the animation starting point to be that point.
And while I can see that I get the point the zoom in effect always starts from the center of the screen. This is what I have as the custom transition:
enum ZoomTransitionMode: Int {
case present, dismiss, pop
}
class ZoomTransition: NSObject{
var zoom = UIView()
var originFrame = CGRect.zero
var startingPoint: CGPoint!
var zoomColor = UIColor.appWhite
var animationDuration = 0.3
var transitionMode: ZoomTransitionMode = .present
}
extension ZoomTransition: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return animationDuration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
switch transitionMode {
case .present:
if let presentedView = transitionContext.view(forKey: UITransitionContextViewKey.to) {
print(startingPoint)
zoom = UIView()
zoom.frame = CGRect(origin: startingPoint, size: CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
zoom.layer.cornerRadius = 20
zoom.backgroundColor = zoomColor
zoom.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
containerView.addSubview(zoom)
presentedView.transform = CGAffineTransform(scaleX: 0.001, y: 0.001)
presentedView.frame = UIScreen.main.bounds
presentedView.alpha = 0
presentedView.backgroundColor = .systemGreen
containerView.addSubview(presentedView)
containerView.bringSubviewToFront(presentedView)
UIView.animate(withDuration: 10, animations: {
self.zoom.transform = CGAffineTransform.identity
presentedView.transform = CGAffineTransform.identity
presentedView.alpha = 1
}) { (didSuccessed) in
transitionContext.completeTransition(didSuccessed)
}
}
default:
return
}
}
I also tried setting the zoom's and the presentedView center as the starting point, but still, the animation starts from the center of the screen instead of the starting point.

Core Animation - modify animation property

I have animation
func startRotate360() {
let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.fromValue = 0
rotation.toValue = Double.pi * 2
rotation.duration = 1
rotation.isCumulative = true
rotation.repeatCount = Float.greatestFiniteMagnitude
self.layer.add(rotation, forKey: "rotationAnimation")
}
What I want is ability to stop animation by setting its repeat count to 1, so it completes current rotation (simply remove animation is not ok because it looks not good)
I try following
func stopRotate360() {
self.layer.animation(forKey: "rotationAnimation")?.repeatCount = 1
}
But I get crash and in console
attempting to modify read-only animation
How to access writable properties ?
Give this a go. You can in fact change CAAnimations that are in progress. There are so many ways. This is the fastest/simplest. You could even stop the animation completely and resume it without the user even noticing.
You can see the start animation function along with the stop. The start animation looks similar to yours while the stop grabs the current rotation from the presentation layer and creates an animation to rotate until complete. I also smoothed out the duration to be a percentage of the time needed to complete based on current rotation z to full rotation based on the running animation. Then I remove the animation with the repeat count and add the new animation. You can see the view rotate smoothly to the final position and stop. You will get the idea. Drop it in and run it and see what you think. Hit the button to start and hit it again to see it finish rotation and stop.
import UIKit
class ViewController: UIViewController {
var animationView = UIView()
var button = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
animationView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
animationView.backgroundColor = .green
animationView.center = view.center
self.view.addSubview(animationView)
let label = UILabel(frame: animationView.bounds)
label.text = "I Spin"
animationView.addSubview(label)
button = UIButton(frame: CGRect(x: 20, y: animationView.frame.maxY + 60, width: view.bounds.width - 40, height: 40))
button.setTitle("Animate", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.addTarget(self, action: #selector(ViewController.pressed), for: .touchUpInside)
self.view.addSubview(button)
}
func pressed(){
if let title = button.titleLabel?.text{
let trans = CATransition()
trans.type = "rippleEffect"
trans.duration = 0.6
button.layer.add(trans, forKey: nil)
switch title {
case "Animate":
//perform animation
button.setTitle("Stop And Finish", for: .normal)
rotateAnimationRepeat()
break
default:
//stop and finish
button.setTitle("Animate", for: .normal)
stopAnimationAndFinish()
break
}
}
}
func rotateAnimationRepeat(){
//just to be sure because of how i did the project
animationView.layer.removeAllAnimations()
let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.fromValue = 0
rotation.toValue = Double.pi * 2
rotation.duration = 0.5
rotation.repeatCount = Float.greatestFiniteMagnitude
//not doing cumlative
animationView.layer.add(rotation, forKey: "rotationAnimation")
}
func stopAnimationAndFinish(){
if let presentation = animationView.layer.presentation(){
if let currentRotation = presentation.value(forKeyPath: "transform.rotation.z") as? CGFloat{
var duration = 0.5
//smooth out duration for change
duration = Double((CGFloat(Double.pi * 2) - currentRotation))/(Double.pi * 2)
animationView.layer.removeAllAnimations()
let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.fromValue = currentRotation
rotation.toValue = Double.pi * 2
rotation.duration = duration * 0.5
animationView.layer.add(rotation, forKey: "rotationAnimation")
}
}
}
}
Result:
2019 typical modern syntax
Setup the arc and the layer like this:
import Foundation
import UIKit
class RoundChaser: UIView {
private let lineThick: CGFloat = 10.0
private let beginFraction: CGFloat = 0.15
// where does the arc drawing begin?
// 0==top, .25==right, .5==bottom, .75==left
private lazy var arcPath: CGPath = {
let b = beginFraction * .pi * 2.0
return UIBezierPath(
arcCenter: bounds.centerOfCGRect(),
radius: bounds.width / 2.0 - lineThick / 2.0,
startAngle: .pi * -0.5 + b,
// recall that .pi * -0.5 is the "top"
endAngle: .pi * 1.5 + b,
clockwise: true
).cgPath
}()
private lazy var arcLayer: CAShapeLayer = {
let l = CAShapeLayer()
l.path = arcPath
l.fillColor = UIColor.clear.cgColor
l.strokeColor = UIColor.purple.cgColor
l.lineWidth = lineThick
l.lineCap = CAShapeLayerLineCap.round
l.strokeStart = 0
l.strokeEnd = 0
// if both are same, it is hidden. initially hidden
layer.addSublayer(l)
return l
}()
then initialization is this easy
open override func layoutSubviews() {
super.layoutSubviews()
arcLayer.frame = bounds
}
finally animation is easy
public func begin() {
CATransaction.begin()
let e : CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd")
e.duration = 2.0
e.fromValue = 0
e.toValue = 1.0
// recall 0 will be our beginFraction, see above
e.repeatCount = .greatestFiniteMagnitude
self.arcLayer.add(e, forKey: nil)
CATransaction.commit()
}
}
Maybe this is not the best solution but it works, as you say you can not modify properties of the CABasicAnimation once is created, also we need to remove the rotation.repeatCount = Float.greatestFiniteMagnitude, if notCAAnimationDelegatemethodanimationDidStop` is never called, with this approach the animation can be stoped without any problems as you need
step 1: first declare a variable flag to mark as you need stop animation in your custom class
var needStop : Bool = false
step 2: add a method to stopAnimation after ends
func stopAnimation()
{
self.needStop = true
}
step 3: add a method to get your custom animation
func getRotate360Animation() ->CAAnimation{
let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.fromValue = 0
rotation.toValue = Double.pi * 2
rotation.duration = 1
rotation.isCumulative = true
rotation.isRemovedOnCompletion = false
return rotation
}
step 4: Modify your startRotate360 func to use your getRotate360Animation() method
func startRotate360() {
let rotationAnimation = self.getRotate360Animation()
rotationAnimation.delegate = self
self.layer.add(rotationAnimation, forKey: "rotationAnimation")
}
step 5: Implement CAAnimationDelegate in your class
extension YOURCLASS : CAAnimationDelegate
{
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if(anim == self.layer?.animation(forKey: "rotationAnimation"))
{
self.layer?.removeAnimation(forKey: "rotationAnimation")
if(!self.needStop){
let animation = self.getRotate360Animation()
animation.delegate = self
self.layer?.add(animation, forKey: "rotationAnimation")
}
}
}
}
This works and was tested
Hope this helps you

CAShapeLayer strange behavior in the first time animation

I've wrote this animation to the CAShapeLayer (pulseLayer) and in the viewDidLoad() :
let pulseLayer = CAShapeLayer()
#IBOutlet weak var btnCart: UIButton!
override func viewDidLoad() {
let longpress = UILongPressGestureRecognizer(target: self, action: #selector(CategoryViewController.longPressGestureRecognized(_:)))
tableView.addGestureRecognizer(longpress)
heartBeatAnimation.duration = 0.75
heartBeatAnimation.repeatCount = Float.infinity
heartBeatAnimation.autoreverses = true
heartBeatAnimation.fromValue = 1.0
heartBeatAnimation.toValue = 1.2
heartBeatAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
btnCart.layer.addSublayer(pulseLayer)
}
func addBtnCartLayerWithAnimation() {
let ovalPath = UIBezierPath(arcCenter: CGPoint(x: btnCart.frame.midX, y: btnCart.frame.midY), radius: btnCart.frame.width * 1.5, startAngle: 0*(CGFloat.pi / 180), endAngle: 360*(CGFloat.pi / 180), clockwise: true)
pulseLayer.path = ovalPath.cgPath
pulseLayer.opacity = 0.15
pulseLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
pulseLayer.bounds = ovalPath.cgPath.boundingBox
pulseLayer.add(heartBeatAnimation, forKey: "heartBeatAnimation")
pulseLayer.transform = CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 1.0)
}
and the removeLayer function is:
func removeLayer() {
pulseLayer.transform = CATransform3DScale(CATransform3DIdentity, 0.1, 0.1, 0.1)
pulseLayer.removeAllAnimations()
}
The problem is when the first animation of the layer is coming from the bottom of the view !
the first animation after viewDidLoad
then after that any invoke for this animation with start from the center(the defined anchor point)
any animation after the first one
Could anyone tell me why this happening ?
the whole class where I defined and used UILongGestureRecognizer on tableView to start/stop the animation :
func longPressGestureRecognized(_ gestureRecognizer: UIGestureRecognizer) {
let longPress = gestureRecognizer as! UILongPressGestureRecognizer
let state = longPress.state
let locationInView = longPress.location(in: tableView)
let indexPath = tableView.indexPathForRow(at: locationInView)
switch state {
case UIGestureRecognizerState.began:
if indexPath != nil {
addBtnCartLayerWithAnimation()
}
case UIGestureRecognizerState.changed:
// some code here not related to the animation
default:
removeLayer()
}
}
When using standalone layers (layers that are not the backing store of a UIView), implicit animations are added for every animatable property change.
You're seeing this effect because the layer is animating its properties from zero to the initial values you're setting in addBtnCartLayerWithAnimation().
What you want to do is to set these initial values without animation (which needs to be done explicitly). You can wrap the change in a transaction in which you disable animations like so:
CATransaction.begin()
CATransaction.setDisableActions(true)
pulseLayer.path = ovalPath.cgPath
pulseLayer.opacity = 0.15
pulseLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
pulseLayer.bounds = ovalPath.cgPath.boundingBox
pulseLayer.transform = CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 1.0)
CATransaction.commit()
pulseLayer.add(heartBeatAnimation, forKey: "heartBeatAnimation")

3D Flip Animation for View Controllers in swift

I am trying to get 3d flip animations among view controllers like this
https://github.com/nicklockwood/CubeController
For the animation.. basing on reverse value I set clock wise direction or anti clock direction
This is the code I am using for animation..
class CusNavAnimController : NSObject, UIViewControllerAnimatedTransitioning {
var reverse: Bool = false
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.25
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView()
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
let toView = toViewController.view
let fromView = fromViewController.view
//
toView.frame = UIScreen.mainScreen().bounds
fromView.frame = UIScreen.mainScreen().bounds
let direction: CGFloat = reverse ? -1 : 1
let const: CGFloat = -0.005
toView.layer.anchorPoint = CGPointMake(direction == 1 ? 0 : 1, 0.5)
fromView.layer.anchorPoint = CGPointMake(direction == 1 ? 1 : 0, 0.5)
var viewFromTransform: CATransform3D = CATransform3DMakeRotation(direction * CGFloat(M_PI_2), 0.0, 1.0, 0.0)
var viewToTransform: CATransform3D = CATransform3DMakeRotation(-direction * CGFloat(M_PI_2), 0.0, 1.0, 0.0)
viewFromTransform.m34 = const
viewToTransform.m34 = const
containerView!.transform = CGAffineTransformMakeTranslation(direction * containerView!.frame.size.width / 2.0, 0)
toView.layer.transform = viewToTransform
containerView!.addSubview(toView)
UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
containerView!.transform = CGAffineTransformMakeTranslation(-direction * containerView!.frame.size.width / 2.0, 0)
fromView.layer.transform = viewFromTransform
toView.layer.transform = CATransform3DIdentity
}, completion: {
finished in
containerView!.transform = CGAffineTransformIdentity
fromView.layer.transform = CATransform3DIdentity
toView.layer.transform = CATransform3DIdentity
fromView.layer.anchorPoint = CGPointMake(0.5, 0.5)
toView.layer.anchorPoint = CGPointMake(0.5, 0.5)
if (transitionContext.transitionWasCancelled()) {
toView.removeFromSuperview()
} else {
fromView.removeFromSuperview()
}
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
})
}}
I am getting the animation but It is not same as the git hub link providing..
For my code.. the fromview is slightly going back and toview coming to front from that point.. can anyone suggest me the changes
Check out TransitionFlipFromLeft and TransitionFlipFromRight in UIViewAnimationOptions

Resources