We all know the UIView’s animateWithDuration:animations:completion:
type method. It is very easy to use and its support dates back to iOS 4. However adopting this method has one major drawback: the impossibility to modify the animation without having to incur in some… headaches.
Luckily starting from iOS 10, Apple introduced UIViewPropertyAnimator
, which allows you to easily create animations that can be dynamically modified.
Let’s see with an example how we can use this class to create a mechanism to toggle a bottom bar’s visibility when the user taps the screen. For starters we are going to need to declare some vars in our ViewController.
class ViewController {
...
let kBottomBarHeight : CGFloat = 100
var bottomBarAnimator: UIViewPropertyAnimator!
var bottomBar: UIView!
var bottomBarIsHidden: Bool = false
...
}
The bottomBarAnimator
var is the object responsible for starting and controlling the animation.
Then we assume that bottomBar
is a simple plain UIView with some black semi-transparent background whose visibility is determined by the boolean var bottomBarIsHidden
.
To toggle the visibility of the bottom bar we need to add a tap gesture recognizer to the main view, so that when the user taps the screen, the toggleBottomBar
method is called.
Let’s make this real by writing some code.
class ViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
//place the bottom bar at the bottom
bottomBar = UIView(frame: CGRect(x: 0.0, y: view.bounds.height-kBottomBarHeight, width: view.bounds.size.width, height: kBottomBarHeight))
//give the bar a black semi-transparent background so that we can see it
bottomBar.backgroundColor = .black.withAlphaComponent(0.35)
view.addSubview(bottomBar)
//add a tap gesture recognizer that triggers the toggling of the bottom bar
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(userDidTap))
tapGestureRecognizer.numberOfTapsRequired = 1
tapGestureRecognizer.numberOfTouchesRequired = 1
view.addGestureRecognizer(tapGestureRecognizer)
}
//the action method triggered by the tap gesture recognizer
@objc func userDidTap(_ gesture: UITapGestureRecognizer) {
if gesture.state == .recognized {
toggleBottomBar()
}
}
}
Now that we initialized the basic components of our class we just need to implement the toggleBottomBar()
method, which is triggered when he user taps the screen.
class ViewController {
...
func toggleBottomBar() {
// stop the animation by using the animator if initialized
bottomBarAnimator?.stopAnimation(true)
// toggle the var that determines if our bottom bar will be hidden or not
bottomBarIsHidden.toggle()
bottomBarAnimator =
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 0.5,
delay: 0.0,
options: .curveEaseIn,
animations: { [weak self] in
guard let self = self else { return }
self.bottomBar.alpha = self.bottomBarIsHidden ? 0.0 : 1.0
})
}
}
The algorithm cancels the toggling animation using the bottomBarAnimator?.stopAnimation(true)
, right before starting a new animation. Then bottomBarIsHidden
var is toggled and based on its value the target alpha value for the animation is determined.