UIImagePickerController无法填充屏幕

63

screenshot

我正在为UIImagePickerController添加自定义叠加层,但是视图底部有一个持久的黑色栏。这是我用来实例化控制器的代码。

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

如果我不隐藏相机控件,返回的控制器将以模态方式显示并正常工作(即全屏显示)。


感谢Ole的建议,我用这段代码使其正常工作:

// Resize the camera preview
        _imagePicker.cameraViewTransform = CGAffineTransformMakeScale(1.0, 1.03);

增加3%的高度就可以了。 当我在屏幕底部添加自定义工具栏时,窗口中再也没有可见的黑色条。

15个回答

55

通过固定值进行缩放并不是一个好主意... 我相信使用此处接受的答案的任何人在 iPhone 5 推出时都已经发现了。

这里有一个代码片段,根据屏幕分辨率动态缩放以消除信封式黑边。

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

@Danpe,你能找到iPhone 5的解决方案吗?我也遇到了同样的问题 - 谢谢! - daspianist
1
@Steve,请您看一下这个关于iPhone 6/iPhone 6Plus的问题,它还没有完全填满屏幕。一个简单的项目,使用图像选择器在父视图控制器中加载,通过复制和粘贴此代码进行测试,将产生与我的相同的结果。请尽快回复我们,谢谢。 - Pavan
@Pavan,我不知道你的情况是否和我的一样,但是因为我使用的是视频而不是照片,所以宽高比是16/9,这样我就可以获得全屏了。 - Hola Soy Edu Feliz Navidad
@HolaSoyEduFelizNavidad,是的伙计。最后我也发现了同样的问题。我最终使用AVFoundation框架设置摄像机来录制视频。然后,您需要使用内置的JPEG方法捕获屏幕,该方法会捕获捕获设备的图像。 - Pavan
4
我无法在 iOS 10 beta 7 上进行缩放。有任何帮助或想法吗? - Rashmi Ranjan mallick
显示剩余5条评论

38
相机的宽高比是4:3,而屏幕的宽高比是3:2。因此,除非您愿意将其裁剪成3:2,否则相机图片无法填满屏幕。为此,请应用适当的比例变换。

这正是我想要的。谢谢!我将更新我的问题,并附上使一切正常的代码。 - kubi
8
有没有一种方法可以适用于所有设备的解决方案?使用上述因素进行缩放会扭曲图像,而使用任何硬编码数字只能适用于具有相同形状和坐标系的设备。是否有一种方法可以找到摄像机视图框架和边界,并调整到窗口的边界? - George

22

嘿,我看到还有一些人在计算 iPhone 5 的比例后仍然会得到底部的黑色条纹。我曾经也有这个问题,但后来我发现你必须将视图平移,使其位于屏幕中央,然后再应用比例。以下是我用来执行这两个步骤的代码,它对我有效!

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

这个解决方案在iPhone 5上运行得很好。然而,正如这个问题中所报道的,在旧版iOS中UIImagePickerController中CGAffineTransformTranslate不起作用(不确定他们何时修复)。此外,似乎你需要在Steve的答案中使用ceilf舍入技巧才能使CGAffineTransformScale在旧版iOS中工作。 - sffc
1
你是对的,我应该加上“运行iOS 7的iPhone 5”。使用CGAffineTransformScale在旧版iOS中没有效果,我曾经抓耳挠腮地苦恼了一段时间。 - strikerdude10
1
工作得很好。节省了很多时间。 - Nazik
@strikerdude10 非常感谢伙计! - Sam
@EpicByte,您能否确认它在iPhone 6和6+上可以正常工作吗? - Sam

11

根据我在iOS 7的iPhone 5S上的经验,要想查看图片中心的全屏预览,你需要连接转换,而不是按顺序进行:

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

为什么转换变换使用 size.height - size.width? - Guy Chen
实际上,这是(屏幕尺寸高度 - 选择器控制器的高度)* 0.5,事实上,屏幕尺寸宽度 * 4/3 等于选择器控制器的高度。 - Enrico Cupellini

10

使用以下代码进行转换:

#define CAMERA_TRANSFORM                    1.12412

_picker.wantsFullScreenLayout = YES;
_picker.cameraViewTransform = CGAffineTransformScale(_picker.cameraViewTransform, CAMERA_TRANSFORM, CAMERA_TRANSFORM);

6

以下是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)

6

我在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)

3
我使用此方法计算比例尺。
// 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);

2
我的问题已经解决 :)
//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;

2
不能在IOS 10上运行 - vualoaithu
1
@vualoaithu,你有什么解决方案吗?因为我也遇到了同样的问题。 - Urmi

2

这些解决方案对我来说并没有完全奏效。在使用iPhone 6+和iPhone 11 Pro运行iOS 13.x时,仍然会在底部出现黑色条。我成功地解决了这个问题,而不需要使用魔术数字,方法是计算偏移量并将其应用于比例计算中心。这种方法适用于6+和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)
    }
}

1
这是唯一一个实际可行的答案 ;) - Oskar Gargas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接