
This video is only available to subscribers. Start a subscription today to get access to this and 472 other videos.
Camera Sounds and UI
This episode is part of a series: Camera Capture and Detection.
1. Intro 1 min |
2. Setting Up The Project 9 min |
3. Camera Preview and Sample Buffer 10 min |
4. Drawing on Top of the Video Preview 14 min |
5. Fixing the Coordinates 7 min |
6. Perspective Outlining 9 min |
7. Camera Sounds and UI 12 min |
8. Rendering the Final Image 15 min |
9. Capturing High Resolution Photos 17 min |
10. Adding a Flash Toggle Camera Control 12 min |
Episode Links
Tapping to take a photo
To take a photo, we will use a UITapGestureRecognizer on the entire screen.
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(onTap(_:)))
view.addGestureRecognizer(tap)
}
@objc func onTap(_ tap: UITapGestureRecognizer) {
// play shutter sound
// stop detecting new rectangles
// flash
// save photo
}
Playing the Shutter Sound
To play the system camera shutter sound, we need to know the ID. Using the wiki link above, we found that this is 1108. We'll start by adding a constant at the top of the class:
let cameraShutterSoundID: SystemSoundID = 1108
Then we use AudioServices to play the sound:
@objc func onTap(_ tap: UITapGestureRecognizer) {
// play shutter sound
AudioServicesPlaySystemSound(cameraShutterSoundID)
// ...
}
Displaying the Flash
For this we'll create a full screen white layer and animate its opacity using Core Animation.
private func flashScreen() {
let flash = CALayer()
flash.frame = view.bounds
flash.backgroundColor = UIColor.white.cgColor
view.layer.addSublayer(flash)
flash.opacity = 0
let anim = CABasicAnimation(keyPath: "opacity")
anim.fromValue = 0
anim.toValue = 1
anim.duration = 0.1
anim.autoreverses = true
anim.isRemovedOnCompletion = true
flash.add(anim, forKey: "flashAnimation")
}
We need to make sure to remove this layer when we're done, so we implement the animation delegate method in an extension. To do this we'll need to set ourselves up as the delegate, conform to the protocol, and stash away the created layer in a property so we can clean it up later.
var flashLayer: CALayer?
// in flashScreen()
anim.delegate = self
self.flashLayer = flash
extension CaptureViewController : CAAnimationDelegate {
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
flashLayer?.removeFromSuperlayer()
flashLayer = nil
detectRectangles = true
}
}
Finally we need to call this right after we play the sound:
@objc func onTap(_ tap: UITapGestureRecognizer) {
// play shutter sound
AudioServicesPlaySystemSound(cameraShutterSoundID)
// stop detecting rectangles
// flash
flashScreen()
}