How would one replicate the bounce effect of the iOS Notification Center window that drops to the bottom of the screen and bounces without ever traveling below the height of the window? This appears to use damping and spring velocity but how do you prevent the object, such as in this case, from overshooting its mark and slinging back?
-
Possibly a duplicate of https://stackoverflow.com/questions/21892105/how-to-create-a-uiview-bounce-animation and https://stackoverflow.com/questions/24904620/pullable-view-like-notification-center-bounces – rmaddy Sep 19 '17 at 01:08
2 Answers
Updated answer: You could build your own custom transition.
Say you have two view controllers, StartController
and EndController
. You want to have this custom transition to happen from StartController to EndController.
1) Create your custom transition object like so:
class CustomSlideTransition: NSObject, UIViewControllerAnimatedTransitioning {
var duration: Double = 1.0
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// Access EndController
let toViewController = transitionContext.viewController(forKey: .to) as! EndController
// Access the container view :
let containerView = transitionContext.containerView
// Move EndController's view frame:
toViewController.view.frame.origin.y -= UIScreen.main.bounds.size.height
containerView.addSubview(toViewController.view)
// Adjust the properties of the spring to what fits your needs the most:
UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 7.0, options: [.curveEaseInOut], animations: {
// Get your EndController's view frame moves back to its final position
toViewController.view.frame.origin.y += UIScreen.main.bounds.size.height
}, completion: { (finished) in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
}
2) In the prepareForSegue
method of your StartController, set the delegate to self
:
class StartController: UIViewController {
// ...
// MARK: PrepareForSegue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationController = segue.destination as? EndController {
destinationController.transitioningDelegate = self
}
}
// ...
}
3) Make StartController conform to the UIViewControllerTransitioningDelegate
:
extension StartController: UIViewControllerTransitioningDelegate {
// MARK: UIViewControllerTransitioningDelegate
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return CustomSlideTransition()
}
}
4) Design your EndController however you want!
Note: You may want to add a custom transition for dismissing EndController as well.
Update: Now if you really don't want your view controller to bounce even a little beyond the window, using a spring
here may not be the best way to go.
Since on iPhone the bounces effect "power" is calculated using the swipe (from the top) offset, you might want to custom even more your animation block using key frame animations, or UIKIT Dynamics
if you're comfortable with.
UIView.animate(withDuration: duration, animations: {
toViewController.view.frame.origin.y += UIScreen.main.bounds.size.height
}, completion: { (finished) in
// Create a custom bounce effect that doesn't go beyond the window (ie. only negative values)
let animation = CAKeyframeAnimation(keyPath: "transform.translation.y")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.duration = 0.75
animation.autoreverses = false
// Depending on how you would like to present EndController, you may want to change the hardcoded values below.
// For example you could make it so that if the user swipes really fast, it would bounce even more..
animation.values = [0, -60, 0, -25, 0]
// Add the key frame animation to the view's layer :
toViewController.view.layer.add(animation, forKey: "bounce")
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
-
I think the question is regarding the animation to open notification center, where it bounces on the bottom of the screen. – nathangitter Sep 19 '17 at 01:04
Take a look into UIKitDynamics
. This will allow you to apply physics and collisions to your views.
You could have a view that drops from the top of the screen and collides with a view at the bottom of the screen. You'll need to use UIGravityBehavior
and UICollisionBehavior
, and should be able to adjust the constants to get the desired effect.

- 9,607
- 3
- 33
- 42