简体   繁体   English

如何让UIImagePicker相机的自定义叠加在iOS 7中全屏显示?

[英]How to get the custom overlay for UIImagePicker camera to be full screen in iOS 7?

I am interested in using a custom overlay for the UIImagePickerController for camera controls that take the entire screen, very similar to what the default Camera app does when switched to the video function. 我有兴趣为UIImagePickerController使用自定义叠加层来拍摄整个屏幕的摄像机控件,非常类似于切换到视频功能时默认的Camera应用程序所做的操作。

I have referenced several questions here on SO on this topic, particularly this one , as well as the Apple example on how to use a custom overlay for the UIImagePickerController, but none of them have been able to produce a successful, full-screen result with iOS 7. 关于这个主题,我在这里引用了几个问题,特别是这个问题 ,以及关于如何为UIImagePickerController使用自定义叠加层的Apple示例 ,但是它们都没有能够产生成功的全屏结果。 IOS 7。

So far, this is what the camera UI looks like with the custom overlay (without any buttons): 到目前为止,这是相机UI与自定义叠加层(没有任何按钮)的样子:

在此输入图像描述

Note that there is a black bar in the bottom of the screen. 请注意,屏幕底部有一个黑条。 I noticed that I could get the black bar removed if I change the cameraAspectRatio to 1, but this distorts the camera zoom as it then has a very zoomed in view. 我注意到如果我将cameraAspectRatio更改为1,我可以删除黑条,但是这会使相机变焦变形,因为它具有非常放大的视图。 Is there a way to have full screen without either distorting the zoom too much (I understand that a small bit is necessary), and also remove the black bar? 有没有办法让全屏没有太多扭曲变焦(我明白一点点是必要的),还删除黑条?

Here is my code that configures the custom overlay: 这是我配置自定义叠加层的代码:

{
        self.imagePickerController.showsCameraControls = NO;

        [[NSBundle mainBundle] loadNibNamed:@"overlayView" owner:self options:nil];
        self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
        self.imagePickerController.cameraOverlayView = self.overlayView;
        self.overlayView = nil;

        // Device's screen size (ignoring rotation intentionally):
        CGSize screenSize = [[UIScreen mainScreen] bounds].size;


        float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
        float imageWidth = floorf(screenSize.width * cameraAspectRatio);
        float scale = ceilf((screenSize.height / imageWidth) * 10.0) / 10.0;

        self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);

    }

Update: 更新:

An additional issue that I noticed is, the picture that is shown in camera preview is always smaller and has less details than the picture that is saved when the method [self.imagePickerController takePicture] . 我注意到的另一个问题是,相机预览中显示的图片总是较小 ,并且细节少于方法[self.imagePickerController takePicture]时保存的图片。 To illustrate: 为了显示:

This is what the keyboard looks like in the camera preview with the black bar below (sorry its a bit shaky): 这是键盘在相机预览中看起来像下面的黑色条(抱歉它有点不稳定):

在此输入图像描述

However, note that the actual captured image in the preview panel has a lot more details as shown here, especially towards the top, as well as both left and right. 但请注意,预览面板中的实际捕获图像具有更多详细信息,如此处所示,尤其是朝向顶部,以及左侧和右侧。

在此输入图像描述

My question is, how would be able to set my camera preview so that what the user sees in preview is exactly the image that it will capture and could be shown to them afterwards? 我的问题是,如何设置我的相机预览,以便用户在预览中看到的是它将捕获的图像,然后可以显示给他们? Thanks! 谢谢!

Update 2 更新2

Here is the entire code in viewDidLoad that sets up the camera controls. 以下是viewDidLoad中设置摄像机控件的完整代码。

- (void)viewDidLoad
{
    [super viewDidLoad];

    //Appearance configuration
    self.navigationItem.hidesBackButton = YES;

    //UIImagePickerController initialization and setup
    self.imagePickerController = [[UIImagePickerController alloc] init];
    self.imagePickerController.delegate = self;
    self.imagePickerController.allowsEditing = NO;
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        self.imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera; //if there is a camera avaliable
    } else {
        self.imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;//otherwise go to the folder
    }
    self.imagePickerController.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeImage, nil];
    if (self.imagePickerController.sourceType == UIImagePickerControllerSourceTypeCamera)
    {
        self.imagePickerController.showsCameraControls = NO;

        [[NSBundle mainBundle] loadNibNamed:@"overlayView" owner:self options:nil];
        self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
        self.imagePickerController.cameraOverlayView = self.overlayView;
        self.overlayView = nil;

        // Device's screen size (ignoring rotation intentionally):
        CGSize screenSize = [[UIScreen mainScreen] bounds].size;

        int heightOffset = 0;

        if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
        {
            heightOffset = 120; //whole screen :)
        }

        float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
        float imageWidth = floorf(screenSize.width * cameraAspectRatio);
        float scale = ceilf(((screenSize.height + heightOffset) / imageWidth) * 10.0) / 10.0;

        self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);

    }
}

And in viewWillAppear , I call the image picker view: viewWillAppear ,我调用了图像选择器视图:

BOOL modalPresent = (BOOL)(self.presentedViewController);
    //Present the Camera UIImagePicker if no image is taken
    if (!appDelegate.imageStorageDictionary[@"picture1"]){
        if (modalPresent == NO){ //checks if the UIImagePickerController is modally active
            [self presentViewController:self.imagePickerController animated:NO completion:nil];
        }
    }

After many attempts, this is what worked for me with many thanks to other people's suggestions. 经过多次尝试,这对我有用,非常感谢其他人的建议。 The following facts were very helpful to know and keep in mind: 以下事实非常有助于了解并牢记:

The camera's points resolution is 426 * 320 . 相机的分辨率 426320 *。 In order for the camera preview's height to be stretched to the phone's screen height of 568, it needs to be multiplied by a factor of 1.3333 when using CGAffineTransformScale . 为了将相机预览的高度拉伸到手机屏幕高度568,使用CGAffineTransformScale时需要乘以因子1.3333。

Note that the below are hard coded with various numbers based on the iPhone 5's screen resolution in points. 请注意,下面的内容是基于iPhone 5的分辨率屏幕分辨率使用各种数字进行硬编码的。 They could be improved by using such objects such as screen.height, screen.width and other variables to make it applicable to iPhone 4/4s dimensions as well. 它们可以通过使用诸如screen.height,screen.width和其他变量之类的对象来改进,以使其适用于iPhone 4 / 4s尺寸。

    self.imagePickerController.showsCameraControls = NO;

    [[NSBundle mainBundle] loadNibNamed:@"overlayView" owner:self options:nil];
    self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
    self.imagePickerController.cameraOverlayView = self.overlayView;
    self.overlayView = nil;

    //For iphone 5+
    //Camera is 426 * 320. Screen height is 568.  Multiply by 1.333 in 5 inch 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;

In Swift 在斯威夫特

 var picker: UIImagePickerController = UIImagePickerController(); picker.sourceType = UIImagePickerControllerSourceType.Camera; picker.showsCameraControls = false; var screenBounds: CGSize = UIScreen.mainScreen().bounds.size; var scale = screenBounds.height / screenBounds.width; picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, scale, scale); 

Make sure that you account for 20px status bar change in iOS7. 确保您在iOS7中考虑20px状态栏更改。 If you are facing a 20px black screen at bottom of the screen then this will be your issue. 如果您在屏幕底部面对20px黑屏,那么这将是您的问题。 You can check that whether the app is running in ios7 or not by one of these preprocessors 您可以通过其中一个预处理器检查应用程序是否在ios7中运行

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

And you can make following changes to your code and see if it works 您可以对代码进行以下更改,看看它是否有效

{
        self.imagePickerController.showsCameraControls = NO;

        [[NSBundle mainBundle] loadNibNamed:@"overlayView" owner:self options:nil];
        self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
        self.imagePickerController.cameraOverlayView = self.overlayView;
        self.overlayView = nil;

        // Device's screen size (ignoring rotation intentionally):
        CGSize screenSize = [[UIScreen mainScreen] bounds].size;

        int heightOffset = 0;

        if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
        {
            heightOffset = 20;
        }

        float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
        float imageWidth = floorf(screenSize.width * cameraAspectRatio);
        float scale = ceilf(((screenSize.height + heightOffset) / imageWidth) * 10.0) / 10.0;

        self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);

    }

Please let me know if it works. 如果有效,请告诉我。 I haven't coded it to test. 我没有编码进行测试。

Because the screen aspect ratio is different than the 4/3 ratio of the camera itself, you need (as you mentioned) to slightly crop the edges in order to have the image extend to the bottom. 由于屏幕宽高比不同于相机本身的4/3比例,因此您需要(如您所述)轻微裁剪边缘以使图像延伸到底部。

In order to do that, you need to have the width be wide enough so that the height can be the full screen. 为此,您需要使宽度足够宽,以便高度可以是全屏。 So, your image width and height must be: 因此,您的图像宽度和高度必须为:

float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
float imageWidth = screenSize.height / cameraAspectRatio;

You'll also probably want the view presenting the camera image to be that width that extends off both sides of the screen. 您还可能希望视图显示相机图像是从屏幕两侧延伸的宽度。

There is a way easier method to get your overlay fullscreen at least tested in iOS 9. 有一种更简单的方法可以在iOS 9中至少测试覆盖全屏。

let view    = ... your overlayView
let bounds  = UIScreen.mainScreen().bounds
view.center = CGPoint(x: bounds.midX, y: bounds.midY)
view.bounds = bounds
self.imagePicker.cameraOverlayView = view

I don't know why you use screen size. 我不知道你为什么使用屏幕尺寸。 Just try this simple code: 试试这个简单的代码:

if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])

{

     UIImagePickerController *controller = [[UIImagePickerController alloc] init];
     controller.sourceType = UIImagePickerControllerSourceTypeCamera;
     controller.allowsEditing = NO;
     controller.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:
     UIImagePickerControllerSourceTypeCamera];
     controller.delegate = self;
     [self presentViewController:controller animated:NO completion:^{}];
}

Try this code to maintain your resultant image in custom size. 尝试使用此代码将结果图像保持为自定义大小。 I got result by using custom method for getting resultant image as custom size. 我通过使用自定义方法获得结果,将结果图像作为自定义大小。

First create IBOutlet for UIImageview . 首先为UIImageview创建IBOutlet

-(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSString *mediaType = info[UIImagePickerControllerMediaType];
[self dismissViewControllerAnimated:YES completion:nil];


if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
    OriginalImage=info[UIImagePickerControllerOriginalImage];
    image = info[UIImagePickerControllerOriginalImage];
//----------------------------------------
     imageview.image = image; //------------- additional method for custom image size
     self resizeImage];


//-----------------------------------------
        if (_newMedia)
            UIImageWriteToSavedPhotosAlbum(image,self,@selector(image:finishedSavingWithError:contextInfo:),nil);

}
else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie])
{
    // Code here to support video if enabled
}

}

//---- Resize the original image by using custom method---------------------- // ----使用自定义方法调整原始图像的大小----------------------

-(void)resizeImage
{
    UIImage *resizeImage = imageview.image;

    float width = 320;
    float height = 320;

    CGSize newSize = CGSizeMake(320,320);
    UIGraphicsBeginImageContextWithOptions(newSize,NO,0.0);
    CGRect rect = CGRectMake(0, 0, width, height);

    float widthRatio = resizeImage.size.width / width;
    float heightRatio = resizeImage.size.height / height;
    float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;

    width = resizeImage.size.width / divisor;
    height = resizeImage.size.height / divisor;

    rect.size.width  = width;
    rect.size.height = height;

    //indent in case of width or height difference
    float offset = (width - height) / 2;
    if (offset > 0) {
        rect.origin.y = offset;
    }
    else {
        rect.origin.x = -offset;
    }

    [resizeImage drawInRect: rect];

    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

imageview.image = smallImage;
imageview.contentMode = UIViewContentModeScaleAspectFit;

}

To solve a similar problem, I instantiated a ViewController from storyboard and used the controller's view as camera overlay. 为了解决类似的问题,我从故事板中实例化了一个ViewController,并将控制器的视图用作相机覆盖。 I don't know if it's what you're looking for, but i used the following code: 我不知道你是否正在寻找它,但我使用了以下代码:

UIImagePickerController *globalPicker = [[UIImagePickerController alloc] init];
globalPicker.delegate = self;
globalPicker.sourceType = UIImagePickerControllerSourceTypeCamera;controller=[self.storyboard instantiateViewControllerWithIdentifier:@"myVC"];
overlayView = controller.view;
UIView *cameraView=[[UIView alloc] initWithFrame:self.view.bounds];
[cameraView addSubview:overlayView];
[globalPicker setCameraOverlayView:cameraView];

Try this code, it works fine for me 试试这个代码,它对我来说很好

UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraUI.showsCameraControls = NO;

CGSize screenSize = [[UIScreen mainScreen] bounds].size;
float cameraAspectRatio = 4.0 / 3.0;
float imageHeight = floorf(screenSize.width * cameraAspectRatio);
float scale = screenSize.height / imageHeight;
float trans = (screenSize.height - imageHeight)/2;
CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, trans);
CGAffineTransform final = CGAffineTransformScale(translate, scale, scale);
cameraUI.cameraViewTransform = final
;
cameraUI.delegate = self;
[self presentViewController:cameraUI animated:YES completion:nil];

This code assumes that the aspect of the original camera preview area is 4:3. 此代码假定原始相机预览区域的方面为4:3。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM