UIImagePickerController doesn't fill screen
I'm adding a custom overlay to the UIImagePickerController and there is a persistant black bar at the bottom of the view. Here is my code to instantiate the controller.
- (UIImagePickerController *)imagePicker {
if (_imagePicker) {
return _imagePicker;
}
_imagePicker = [[UIImagePickerController alloc] init];
_imagePicker.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
_imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
_imagePicker.showsCameraControls = NO;
_imagePicker.wantsFullScreenLayout = YES;
_imagePicker.navigationBarHidden = YES;
_imagePicker.toolbarHidden = YES;
} else {
_imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
return _imagePicker;
}
The returned controller is displayed modally and w开发者_如何转开发orks just fine (i.e. displays full screen) when I'm not hiding the camera controls.
Thanks to Ole's suggestion I got it working with this code:
// Resize the camera preview
_imagePicker.cameraViewTransform = CGAffineTransformMakeScale(1.0, 1.03);
A 3% increase in height worked just fine. When I add my custom toolbar at the bottom of the screen there is no longer a visible black bar across the window.
Scaling by a fixed value isn't a good idea... as I'm sure anyone who used the accepted answer here probably found out when the iPhone 5 came out.
Here's a code snippet to scale dynamically based on the screen resolution to eliminate the letter boxing.
// Device's screen size (ignoring rotation intentionally):
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
// iOS is going to calculate a size which constrains the 4:3 aspect ratio
// to the screen size. We're basically mimicking that here to determine
// what size the system will likely display the image at on screen.
// NOTE: screenSize.width may seem odd in this calculation - but, remember,
// the devices only take 4:3 images when they are oriented *sideways*.
float cameraAspectRatio = 4.0 / 3.0;
float imageWidth = floorf(screenSize.width * cameraAspectRatio);
float scale = ceilf((screenSize.height / imageWidth) * 10.0) / 10.0;
self.ipc.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);
The camera's aspect ratio is 4:3 and the screen's aspect ratio is 3:2. So there is simply no way for the camera picture to fill the screen unless you're willing to crop is to 3:2. To do that, apply an appropriate scale transform.
Hey I saw some people were still getting the black bar at the bottom after calculating the scale for the iPhone 5. I had this problem for a while but then I figured out you have to translate the view so it is in the middle of the screen and then apply the scale. Here is my code for doing those two things and it works for me!
CGSize screenBounds = [UIScreen mainScreen].bounds.size;
CGFloat cameraAspectRatio = 4.0f/3.0f;
CGFloat camViewHeight = screenBounds.width * cameraAspectRatio;
CGFloat scale = screenBounds.height / camViewHeight;
m_imagePickerController.cameraViewTransform = CGAffineTransformMakeTranslation(0, (screenBounds.height - camViewHeight) / 2.0);
m_imagePickerController.cameraViewTransform = CGAffineTransformScale(m_imagePickerController.cameraViewTransform, scale, scale);
From my experience on iOS 7, iphone 5S, to see the center of the picture into the full-screen preview you have to concatenate the transformations, not make them sequentially:
pickerController.cameraOverlayView = self.view;
CGSize screenSize = [[UIScreen mainScreen] bounds].size; // 320 x 568
float scale = screenSize.height / screenSize.width*3/4; // screen height divided by the pickerController height ... or: 568 / ( 320*4/3 )
CGAffineTransform translate=CGAffineTransformMakeTranslation(0,(screenSize.height - screenSize.width*4/3)*0.5);
CGAffineTransform fullScreen=CGAffineTransformMakeScale(scale, scale);
pickerController.cameraViewTransform =CGAffineTransformConcat(fullScreen, translate);
Transform it with this:
#define CAMERA_TRANSFORM 1.12412
_picker.wantsFullScreenLayout = YES;
_picker.cameraViewTransform = CGAffineTransformScale(_picker.cameraViewTransform, CAMERA_TRANSFORM, CAMERA_TRANSFORM);
And here the answer in Swift.
let screenSize:CGSize = UIScreen.mainScreen().bounds.size
let ratio:CGFloat = 4.0 / 3.0
let cameraHeight:CGFloat = screenSize.width * ratio
let scale:CGFloat = screenSize.height / cameraHeight
let imag:UIImagePickerController = UIImagePickerController()
imag.cameraViewTransform = CGAffineTransformMakeTranslation(0, (screenSize.height - cameraHeight) / 2.0)
imag.cameraViewTransform = CGAffineTransformScale(imag.cameraViewTransform, scale, scale)
This worked for me on iOS 10:
let screenSize = UIScreen.main.bounds.size
let cameraAspectRatio = CGFloat(4.0 / 3.0)
let cameraImageHeight = screenSize.width * cameraAspectRatio
let scale = screenSize.height / cameraImageHeight
imagePickerController.cameraViewTransform = CGAffineTransform(translationX: 0, y: (screenSize.height - cameraImageHeight)/2)
imagePickerController.cameraViewTransform = imagePickerController.cameraViewTransform.scaledBy(x: scale, y: scale)
I used this method to calculate the scale.
// get the screen size
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
// establish the height to width ratio of the camera
float heightRatio = 4.0f / 3.0f;
// calculate the height of the camera based on the screen width
float cameraHeight = screenSize.width * heightRatio;
// calculate the ratio that the camera height needs to be scaled by
float scale = screenSize.height / cameraHeight;
imagePicker.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);
These solutions did not work in total for me. There was still a black bar at the bottom running under iOS 13.x and using an iPhone 6+ and an iPhone 11 Pro. I was able to resolve for both, without using magic numbers, by calculating the offset to center and applying that to the scale calculation. This worked again with both a 6+ and an 11 Pro.
let screenSize = UIScreen.main.bounds.size
let cameraAspectRatio = CGFloat(4.0 / 3.0)
let cameraImageHeight = screenSize.width * cameraAspectRatio
let offsetToCenter = screenSize.height - cameraImageHeight
let scale = (screenSize.height + offsetToCenter) / cameraImageHeight
if UIImagePickerController.isSourceTypeAvailable(.camera) {
myPickerController.delegate = self
myPickerController.sourceType = .camera
myPickerController.showsCameraControls = false
myPickerController.allowsEditing = false
myPickerController.cameraViewTransform = CGAffineTransform(scaleX: scale, y: scale)
myPickerController.cameraOverlayView = CameraOverlay(frame: vc.view.frame, delegate: self)
currentVC.present(myPickerController, animated: true)
}
}
my issue solved :)
//Camera is 426 * 320. Screen height is 568. Multiply by 1.333 in 5 inch (iPhone5) to fill vertical
CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 71.0); //This slots the preview exactly in the middle of the screen by moving it down 71 points
self.imagePickerController.cameraViewTransform = translate;
CGAffineTransform scale = CGAffineTransformScale(translate, 1.333333, 1.333333);
self.imagePickerController.cameraViewTransform = scale;
Swift 5
100% working Easy Solution If you want show camera in some custom UIView so use that code and camera will be show in full screen
class ViewController: UIViewController, UINavigationControllerDelegate,UIImagePickerControllerDelegate {
}
upper section is for delegate and bottom is function
//Mark:- Call this function and enjoy
var imagePickers:UIImagePickerController?
func addCameraInView(){
imagePickers = UIImagePickerController()
if UIImagePickerController.isCameraDeviceAvailable( UIImagePickerController.CameraDevice.rear) {
imagePickers?.delegate = self
imagePickers?.sourceType = UIImagePickerController.SourceType.camera
//imagePickers?.view.frame = customCameraView.bounds
imagePickers?.view.contentMode = .scaleAspectFit
imagePickers?.allowsEditing = false
imagePickers?.showsCameraControls = false
imagePickers?.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
//Mark:- this part is handling camera in full screen in a custom view
// let screenSize = UIScreen.main.bounds.size
let screenSize = customCameraView.bounds.size
let cameraAspectRatio = CGFloat(4.0 / 4.0)
let cameraImageHeight = screenSize.width * cameraAspectRatio
let scale = screenSize.height / cameraImageHeight
imagePickers?.cameraViewTransform = CGAffineTransform(translationX: 0, y: (screenSize.height - cameraImageHeight)/2)
imagePickers?.cameraViewTransform = (imagePickers?.cameraViewTransform.scaledBy(x: scale, y: scale))!
// Add the child's View as a subview
self.customCameraView.addSubview((imagePickers?.view)!)
}
}
if you want it from main screen then you need to change the ratio (4.0/3.0)
let screenSize = UIScreen.main.bounds.size
let cameraAspectRatio = CGFloat(4.0 / 3.0)
This is what works for me with Swift 4
let screenSize: CGSize = picker.view.safeAreaLayoutGuide.layoutFrame.size
let ratio: CGFloat = 4.0 / 3.0
let cameraHeight: CGFloat = screenSize.width * ratio
let scale: CGFloat = (screenSize.height + 80) / cameraHeight
picker.cameraViewTransform = picker.cameraViewTransform.scaledBy(x: scale, y: scale)
Following works for me to eliminate Letter boxing and capture full screen images matching exact device height. The code is written in Swift 5.
// Eliminate letter boxing
let screenSize = UIScreen.main.bounds
let cameraAspectRatio: CGFloat = 4.0 / 3.0
let imageHeight = screenSize.width * cameraAspectRatio
let scale = ceil((screenSize.height / imageHeight) * 10.0) / 10.0
var transform = CGAffineTransform(translationX: 0, y: (screenSize.height - imageHeight) / 2)
transform = transform.scaledBy(x: scale, y: scale)
picker.cameraViewTransform = transform
Try use this code:
picker.wantsFullScreenLayout = YES;
CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 71.0);
CGAffineTransform scale = CGAffineTransformScale(translate, 1.333333, 1.47);
picker.view.transform = scale;
PickerViewController.m
#define CAMERA_TRANSFORM 1.8
- (void)viewDidAppear:(BOOL)animated
{
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
// type = UIImagePickerControllerSourceTypeCamera;
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.allowsEditing = NO;
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.showsCameraControls=NO;
picker.extendedLayoutIncludesOpaqueBars = YES;
picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, CAMERA_TRANSFORM , CAMERA_TRANSFORM);
[self presentViewController:picker animated:YES completion:nil];
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Message"
message:@"Device have no camera"
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
}
精彩评论