如何让 UIImagePicker 相机的自定义叠加在 iOS 7 中全屏显示?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20779628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the custom overlay for UIImagePicker camera to be full screen in iOS 7?
提问by daspianist
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
为占据整个屏幕的相机控件使用自定义叠加层,这与切换到视频功能时默认相机应用程序所做的非常相似。
I have referenced several questions here on SO on this topic, particularly this one, as well as the Apple exampleon 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 couldget 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. 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?
请注意,屏幕底部有一个黑条。我注意到,如果我将 更改为 1,我可以移除黑条cameraAspectRatio
,但这会扭曲相机变焦,因为它的视图会非常放大。有没有办法在不过度扭曲缩放的情况下全屏显示(我知道需要一点点),并且还删除黑条?
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 smallerand has less details than the picture that is saved when the method [self.imagePickerController takePicture]
. To illustrate:
另外一个问题,我注意到的是,就是在摄像头预览显示的画面始终是小,并具有比保存方法时图像不太细节[self.imagePickerController takePicture]
。为了显示:
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];
}
}
回答by daspianist
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 pointsresolution is 426 * 320. 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
.
相机的点分辨率为426 * 320。为了将相机预览的高度拉伸到手机屏幕高度 568,使用 时需要乘以 1.3333 的系数CGAffineTransformScale
。
Note that the below are hard coded with various numbers based on the iPhone 5's screen resolution in points. 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.
请注意,以下是根据 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;
回答by Vikramaditya
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);
回答by Kamran Khan
Make sure that you account for 20px status bar change in iOS7. If you are facing a 20px black screen at bottom of the screen then this will be your issue. You can check that whether the app is running in ios7 or not by one of these preprocessors
确保你考虑到了 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)
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.
请让我知道它是否有效。我没有编码它来测试。
回答by Kendall Helmstetter Gelner
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.
您可能还希望呈现相机图像的视图具有超出屏幕两侧的宽度。
回答by Nicolas Manzini
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
回答by Naeem Paracha
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:^{}];
}
回答by wzienrgo
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。
回答by Rajesh Loganathan
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
.
首先IBOutlet
为UIImageview
.
-(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;
}
回答by Nico.S
To solve a similar problem, I instantiated a ViewController from storyboard and used the controller's view as camera overlay. I don't know if it's what you're looking for, but i used the following code:
为了解决类似的问题,我从故事板实例化了一个 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];