I have a view where the user needs to make a selection before a button will work. To make this more obvious, I want to have the element that represents the selection that needs to be done blink if the (greyed-out) button is pressed first. I.e. I want to indicate that this is an error in that state and lead the user's attention to the UI element they need to use first.
My current attempt to have the element (self.display
in the code below) quickly blink two times is the following:
@IBAction func inactiveButtonClick() {
let period = 0.16
UIView.animate(withDuration: period/2, delay: 0.0, options: [.curveEaseInOut, .autoreverse, .repeat], animations: {
self.display.alpha = 0
}, completion: { _ -> Void in
self.display.alpha = 1
})
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + period*2, execute: {
self.display.layer.removeAllAnimations()
})
}
This works quite well, but doesn't feel 100% right, and the animation is sometimes cut off fractions of a second before it finishes. I guess I could queue two animations, but I wonder if there is an easier way of accomplishing this. Are there any built-in ways to have a UI element blink to indicate an error? If not, are there any “known good” combinations of curves and frequencies that convey this to a user?
Keyframe animations seem like a perfect fit in this scenario:
So you first create a key frame animation with a duration of period. Inside of the animations block you can add custom keyframe animations by specifing relative start time (between 0 and 1 - 1 beign end of keyframe animation, so your duration).
So first we add animation that starts at the beginning and its relative duration is 0.5 so 1/2 of the total animation duration. Second animation will start when first finishes at 1/2 of total animation and continue for the rest 1/2 of animation time.
Hope this helps