开发者

UIImagePickerController doesn't fill screen

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)

UIImagePickerController doesn't fill screen


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];
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜