I'm developing an app that permits user to takes photo.
I've started using AVCam apple provides but i'm actually have a problem
Simply i cannot position the camera layer where i want but it's positioned automatically on center of the View
On the left side you can see what i actually have, on the right side what i'd like to have.
The View that contains the preview that comes from the camera is a UIView
subclass and this is the code
class AVPreviewView : UIView {
override class func layerClass() -> AnyClass {
return AVCaptureVideoPreviewLayer.self
}
func session () -> AVCaptureSession {
return (self.layer as AVCaptureVideoPreviewLayer).session
}
func setSession(session : AVCaptureSession) -> Void {
(self.layer as AVCaptureVideoPreviewLayer).session = session;
(self.layer as AVCaptureVideoPreviewLayer).videoGravity = AVLayerVideoGravityResizeAspect;
}
}
Any help is appreciated
First get your screen size so you can calculate the aspect ratio
let screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
var aspectRatio: CGFloat = 1.0
var viewFinderHeight: CGFloat = 0.0
var viewFinderWidth: CGFloat = 0.0
var viewFinderMarginLeft: CGFloat = 0.0
var viewFinderMarginTop: CGFlaot = 0.0
Now calculate the size of the preview layer.
func setSession(session : AVCaptureSession) -> Void {
if screenWidth > screenHeight {
aspectRatio = screenHeight / screenWidth * aspectRatio
viewFinderWidth = self.bounds.width
viewFinderHeight = self.bounds.height * aspectRatio
viewFinderMarginTop *= aspectRatio
} else {
aspectRatio = screenWidth / screenHeight
viewFinderWidth = self.bounds.width * aspectRatio
viewFinderHeight = self.bounds.height
viewFinderMarginLeft *= aspectRatio
}
(self.layer as AVCaptureVideoPreviewLayer).session = session;
Set the layer's videoGravity
to AVLayerVideoGravityResizeAspectFill
so that the layer stretches to fill given your custom view.
(self.layer as AVCaptureVideoPreviewLayer).videoGravity = AVLayerVideoGravityResizeAspectFill;
Finally, set the frame of your preview layer to the values calculated above with any offset that you like.
(self.layer as AVCaptureVideoPreviewLayer).frame = CGRectMake(viewFinderMarginLeft, viewFinderMarginTop, viewFinderWidth, viewFinderHeight)
}
This may take some tweaking since I haven't tested it live, but you should be able to create a more flexible VideoPreviewArea delimited by the bounds of your APPreviewView.
What you're seeing isn't the layer being positioned as much as it is the aspect of the view/layer doesn't match the aspect ratio of the camera, so it's using the videoGravity
property and aspect filling it (which always implies centered)
When you create the layer, size it so that the aspect ratio is correct, then position it at will. Or, in this case, resize the view to the correct aspect ratio, then the view can be positioned at will.
I had a similar problem I fix it doing this:
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
previewLayer.anchorPoint = videoLayer.bounds.origin
previewLayer.frame = CGRect(x: videoLayer.bounds.origin.x, y: videoLayer.bounds.origin.y, width: videoLayer.frame.size.width, height: videoLayer.frame.size.height)
// videoLayer.addSubview(previewLayer)
// previewLayer.
videoLayer.layer.addSublayer(previewLayer)
captureSession.startRunning()
Hope this can help :)
I ran into this problem and the code provided did not fix the situation even though the code was working. I have been building my app using the interface builder.
In the the attributes inspector there under extend edges there are settings which all the view to be extended under tops bars and under bottom bars. My settings had these checked which was throwing off calculations for the positioning of the view.
Extend edges settings: