I have managed (through the help of StackOverflow) to add a partial page curl programatically to my UIPageViewController. This is used a hint to the user that they have completed that page/screen and can proceed.
The code looks like this:
let animation = CATransition()
animation.duration = 0.3
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
animation.endProgress = 0.2
animation.type = "pageCurl"
myPageViewController.view.layer.add(animation, forKey: "MyTransition")
And here's what it looks like (apologies for poor quality - mp4 to gif not so good)

What i'd really like to do now is add some spring to that animation, so it looks a little nicer. But i'm finding it really difficult to get any information off Google (may not even be possible?).
This is what i've tried:
// Can't see an animation type on here, maybe keyPath is used as the type?
let x = CASpringAnimation(keyPath: "pageCurl")
// No endProgress either, just trying some random values now
x.fromValue = 0
x.toValue = 1
// No idea - found on Google - can play with the settings later
x.damping = 5
x.duration = x.settlingDuration
// These look familiar from my working animation, so i'll set these!
x.fillMode = kCAFillModeForwards
x.isRemovedOnCompletion = false
myPageViewController.view.layer.add(x, forKey: "MyNewTransition")
... and it does absolutely nothing. Not even a crash. I expect it's because you cant use pageCurl as the keyPath, iOS doesn't know what to do with it, so it's ignored.
Here's a video showing roughly what I want from this...

So does anyone have any idea if it's possible to do this pageCurl animation, but with some spring?
Edit for new gifs:
class ViewController: UIViewController {
var animated:Bool = false
var counter: Int = 0
var transition = CATransition()
override func viewDidLoad() {
super.viewDidLoad()
view.layer.backgroundColor = UIColor.white.cgColor
}
@IBAction func animate(_ sender: Any) {
animated = false
counter = 0
animateCurlPage(start: 0.0, end: 0.35, duration: 0.4)
}
func animateCurlPage(start: Float, end: Float, duration: CFTimeInterval) {
if (counter == 3) { return }
UIView.animate(withDuration: duration, animations: {
if (self.animated) { return }
self.transition.type = "pageCurl"
self.transition.subtype = kCATransitionFromBottom
self.transition.duration = duration
self.transition.startProgress = start
self.transition.endProgress = end
self.transition.delegate = self
self.transition.fillMode = kCAFillModeForwards
self.transition.isRemovedOnCompletion = false
self.view.layer.add(self.transition, forKey: "transition1")
})
if animated {
animateRepeatCurlPage()
}
}
func animateRepeatCurlPage() {
UIView.animate(withDuration: 0.15, animations: {
self.transition.type = "pageCurl"
self.transition.subtype = kCATransitionFromBottom
self.transition.duration = 0.15
self.transition.startProgress = 0.32
self.transition.endProgress = 0.31
self.transition.delegate = self
self.transition.fillMode = kCAFillModeForwards
self.transition.isRemovedOnCompletion = (self.counter == 2) ? true : false
self.view.layer.add(self.transition, forKey: "transition2")
})
counter += 1
}
}
extension ViewController: CAAnimationDelegate {
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
animateCurlPage(start: 0.35, end: 0.32, duration: 0.2)
animated = true
}
}
Here is the result of the code:

I hope you will not add a new gif again :D ! Cheers !
Edit: You should add the gifs before my answer, now it looks like I added a wrong solution for your good question.
For page curl animation and spring animation you need to execute two animations in the same time, so you need an animation group to be able to handle them and also one of the most important thing is to have different key for each animation. In the current example if you use the same key: transition for both animations, only a single animation will be executed and usually, the last one.
You can play a bit the animation parameters, I just added some arbitrary values here.
@IBAction func animate(_ sender: Any) {
let animationGroup = CAAnimationGroup()
animationGroup.duration = 5
animationGroup.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear)
animationGroup.animations = [animateCurlPage(), animateSpringTransition()]
view.layer.add(animationGroup, forKey: "animation")
}
func animateCurlPage() -> CAAnimation {
let transition = CATransition()
transition.type = "pageCurl"
transition.subtype = kCATransitionFromRight
transition.duration = 1
view.layer.add(transition, forKey: "transition")
return transition
}
func animateSpringTransition() -> CAAnimation{
let transitionX = CASpringAnimation(keyPath: "position.y")
transitionX.duration = 0.5
transitionX.fromValue = view.layer.position.y
transitionX.toValue = view.layer.position.y - 60
transitionX.damping = 5.0
transitionX.initialVelocity = 1.0
transitionX.stiffness = 20.0
transitionX.beginTime = CACurrentMediaTime()
view.layer.add(transitionX, forKey: "transitionX")
return transitionX
}
Here is the result: 
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With