【问题标题】:How to get the custom overlay for UIImagePicker camera to be full screen in iOS 7?如何让 UIImagePicker 相机的自定义覆盖在 iOS 7 中全屏显示?
【发布时间】:2013-12-26 05:32:11
【问题描述】:

我有兴趣为 UIImagePickerController 使用自定义叠加层来控制占据整个屏幕的相机控件,这与默认相机应用在切换到视频功能时所做的非常相似。

我在这里参考了几个关于这个主题的问题,特别是这个one,以及关于如何为 UIImagePickerController 使用自定义叠加层的Apple example,但没有一个能够产生成功, iOS 7 的全屏结果。

到目前为止,这是带有自定义叠加层(没有任何按钮)的相机 UI:

请注意,屏幕底部有一个黑条。我注意到如果我将cameraAspectRatio 更改为 1,我可以移除黑条,但这会扭曲相机变焦,因为它的视野非常放大。有没有一种方法可以在不过度扭曲缩放的情况下实现全屏(我知道有一点是必要的),并且还可以移除黑条?

这是我配置自定义叠加层的代码:

{
        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);

    }

更新:

我注意到的另一个问题是,相机预览中显示的图片总是更小,并且比使用[self.imagePickerController takePicture] 方法保存的图片具有更少的细节。举例说明:

这是相机预览中键盘的样子,下面有黑条(抱歉有点摇晃):

但是,请注意,预览面板中实际捕获的图像有更多细节,如此处所示,尤其是顶部以及左右两侧。

我的问题是,如何设置我的相机预览,以便用户在预览中看到的正是它将捕获的图像并且可以在之后显示给他们?谢谢!

更新 2

这是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);

    }
}

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

【问题讨论】:

  • 嘿.. 你能告诉我你是如何实现“拍摄下一张照片”功能的吗?我希望我的相机在点击照片后仍处于拍摄模式。
  • @daspianist 您是否找到了解决方案,因为我也面临类似的问题。底部出现一个黑条

标签: ios iphone ios7 uiimagepickercontroller


【解决方案1】:

经过多次尝试,这对我有用,非常感谢其他人的建议。以下事实非常有助于了解和牢记:

相机的分辨率为426 * 320。为了让相机预览的高度拉伸到手机屏幕高度568,使用CGAffineTransformScale时需要乘以1.3333倍。

请注意,以下内容是根据 iPhone 5 的屏幕分辨率(以点为单位)使用各种数字进行硬编码的。它们可以通过使用诸如 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;

【讨论】:

  • 如果你把它全部拉伸到适合高度,那么宽度会发生什么变化?
  • 左右两边被截断。例如,如果您打开默认的相机应用程序并切换到视频,那么如果您应用此代码,则带有尺寸的填充屏幕正是您所看到的。
  • 有没有办法在不使用自定义叠加层的情况下完成此任务?使用股票相机控件...
  • @Jacob 本教程 (appcoda.com/ios-programming-camera-iphone-app) 很好地概述了如何使用标准 iOS 相机控件。
  • 感谢发帖,真的很有帮助:)
【解决方案2】:

在斯威夫特中

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);

【讨论】:

  • 我试过这段代码,它确实使我的默认 ios 相机透明。但唯一的问题是您在拍照时所看到的视图比拍摄照片的预览放大得多。你知道如何解决这个问题吗?
  • 你试过缩放值吗,var scale = screenBounds.width/screenBounds.height;
  • 我刚试过,它给我的相机屏幕很小。我听说我应该将相机屏幕放大并裁剪掉不适合手机屏幕尺寸的其余部分,以使其像 snapchat 相机视图。不知道我应该使用什么比例并裁剪其余部分。
【解决方案3】:

确保您考虑了 iOS7 中 20px 状态栏的变化。如果您在屏幕底部面对 20 像素的黑屏,那么这将是您的问题。您可以通过这些预处理器之一检查应用程序是否在 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)

您可以对您的代码进行以下更改,看看它是否有效

{
        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);

    }

请让我知道它是否有效。我还没有编写代码来测试。

【讨论】:

  • 感谢高度偏移方法的建议。在偏移 20 处,它有轻微的影响,但当我尝试 120 时,它设法覆盖了整个底部黑条。然而,问题是在偏移 120 的情况下,相机预览变得非常放大,尽管它拍摄的照片仍然被缩小了。如果有帮助,我可以提供一些预览图与真实图片的截图。
  • 大约 120 是我在计算屏幕尺寸时得到的结果。这就是必须放大多少才能以相机自然捕获的纵横比从上到下填充屏幕......您的选择是裁剪您拍摄的照片以匹配您在预览中显示的内容,扭曲图像以便它垂直拉伸以填充 iPhone5 上的屏幕,或者使图像居中,以便在顶部和底部有较小的条。就我个人而言,我会推荐这些酒吧,无论如何它都会在 iPhone 4(或 4s)上消失。
  • 从第一张截图来看,self.imagePickerController 也与屏幕顶部对齐。我将尝试编写代码并在此处测试并发送给您。
  • 也可以查看这个帖子stackoverflow.com/questions/19046070/…
  • @kamran 我确实为视图启用了自动布局。相机视图确实被完全拉伸(这很棒 - 感谢这个建议),所以现在我正在研究如何裁剪图像的哪一部分,以便它看起来与相机视图中的图像预览完全一样。
【解决方案4】:

由于屏幕纵横比与相机本身的 4/3 比例不同,因此您需要(如您所述)稍微裁剪边缘以使图像延伸到底部。

为了做到这一点,您需要让宽度足够宽,以便高度可以是全屏。因此,您的图像宽度和高度必须是:

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

您可能还希望显示相机图像的视图具有延伸到屏幕两侧的宽度。

【讨论】:

  • 感谢分享这个结果。不幸的是,使用它仍然会导致屏幕底部显示黑条。呈现相机预览图像的叠加视图当前设置为适合整个屏幕 (320 * 568) - 您的意思是该视图应该被拉伸到比这更大吗?
  • 我想是的,是的。可能是当前视图设置为宽高比合适。
  • 感谢您的建议。我确保覆盖视图(来自 xib)都显示为要填充的比例,并将视图拉伸到各种尺寸以进行测试,包括非常大的尺寸,例如 480*680。但是,我仍然得到底部的黑条。
【解决方案5】:

有一种更简单的方法可以让你的覆盖全屏至少在 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

【讨论】:

    【解决方案6】:

    我不知道你为什么使用屏幕尺寸。试试这个简单的代码:

    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:^{}];
    }
    

    【讨论】:

    • 不幸的是,这仅在我想使用默认 UIImagePicker 时才有效,但不适用于自定义叠加层。
    • 您使用叠加层的目的是什么?
    • 我想使用自定义叠加层,以便在拍照时相机视图占据整个屏幕。
    • 尝试 cameraViewTransform 全屏。 CGFloat camScaleup = 2; imagePicker.cameraViewTransform = CGAffineTransformScale(imagePicker.cameraViewTransform, camScaleup, camScaleup);
    【解决方案7】:

    尝试使用此代码将生成的图像保持为自定义大小。我通过使用自定义方法将结果图像作为自定义大小得到了结果。

    首先为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
    }
    
    }
    

    //---- 使用自定义方法调整原图大小---------------------

    -(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;
    
    }
    

    【讨论】:

      【解决方案8】:

      为了解决类似的问题,我从情节提要中实例化了一个 ViewController 并将控制器的视图用作相机覆盖。 我不知道这是否是您要查找的内容,但我使用了以下代码:

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

      【讨论】:

        【解决方案9】:

        试试这个代码,它对我来说很好用

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

        此代码假设原始相机预览区域的宽高比为 4:3。

        【讨论】:

          猜你喜欢
          • 2016-04-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多