Making your UI Elements to bounce with Bouncable Protocol
In this article, we will be making a swift protocol which when conformed by any class which inherits UIView
, can bounce by transform scale. We are not going to cover the whole bounce and fly animation in this post though. We will come back to making a view flyable later down the series with Flyable protocol. For this we are going to add CABasicAnimation
, to the layer of the desired view, thus making it bounce.
This is Part 2, of a series Swift Protocols and adding those nifty functionalities in your app using them. The base article of the series can be found here : https://medium.com/@ashwinshres/swift-protocols-and-adding-those-nifty-functionalities-in-your-app-using-them-50a9680891ef
In the previous part of this series: we have already gone through the basics of CALayer and CABasicAnimation
, so we will jump directly to implemenation in this article.
Here, we are trying to scale any view by its root layer bounds. So what do we need to to that?
We need, an animation by the keypath of “transform.scale.xy”
, the one we talked in previous article. We also need the initial and final scale of the transformation, the duration of animation, and the repeat count for the animation. In this, we will be adding animation completion handler too, to notify the caller that the animation was completed. From this, we can figure out the protocol defination, the blueprint of methods and properties we need to cally out this bounce functionality.
protocol Bouncable: UIView {
func bounce(didBounce: @escaping () -> ())
var bounceScale: CGFloat { set get }
var initialScale: CGFloat { set get }
var bounceRepeatCount: Float { set get }
var bounceDuration: Double { set get }
}
That’s the blue print of our protocol.
Now coming to the core implementation, as I have already talked in the first part, about how we are going to demo a sample implementation by the end of this series by adding all type of protocols, we are going to add a default implementation of func bounce(didBounce: @escaping () -> ())
as this same functionality will be shared by many classes adopting this protocol.
extension Bouncable { func bounce(didBounce: @escaping () -> ()) {
CATransaction.begin()
let scaleAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
scaleAnimation.duration = bounceDuration
scaleAnimation.repeatCount = bounceRepeatCount
scaleAnimation.autoreverses = true
scaleAnimation.fromValue = initialScale
scaleAnimation.toValue = bounceScale
CATransaction.setCompletionBlock {
didBounce()
}
layer.add(scaleAnimation, forKey: "scale")
CATransaction.commit()
}}
Here, we have used CATransaction
CATransaction
A mechanism for grouping multiple layer-tree operations into atomic updates to the render tree.
CATransaction
is used here to get notified when animation completes, so we can notify back to caller with out handler.
class BounceAbleView: UIView, Bouncable { var bounceDuration: Double = 2.0
var bounceScale: CGFloat = 2.0
var initialScale: CGFloat = 0.5
var bounceRepeatCount: Float = 2}class ProductViewController: UIViewController { @IBOutlet var bouncableView: BouncAbleView! override func viewDidLoad() {
super.viewDidLoad()
bouncableView.bounce {
// do what you want to do after bounce completed
}
}}
So, this is much the gist of the thing.
In the next article , we will be adding a Tapable
functionality with protocol to a UIView
or any class which inherits UIView
.
If you have any questions or suggestions, feel free to post them in the comment section.
Thanks for reading.
Happy Coding 🙂