在 iPad 上以纵向模式启动图像选择器
Posted
技术标签:
【中文标题】在 iPad 上以纵向模式启动图像选择器【英文标题】:Launching Image Picker in Portrait Mode on iPad 【发布时间】:2012-07-14 06:56:05 【问题描述】:我正在使用以下代码在我的 iPad 应用程序(使用 Cocos2D)中启动图像选择器:
UIImagePickerController * imagePickerController = [[UIImagePickerController alloc] init];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.showsCameraControls = YES;
imagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
imagePickerController.delegate = self;
imagePickerController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
[self.view addSubview:imagePickerController.view];
[self presentModalViewController:imagePickerController animated:YES];
我希望它一直以纵向模式启动,但它总是这样启动:
图片以纵向显示,图片选择器 UI 为横向模式。但是当我捕获图像时,它会顺时针旋转 90 度。
我希望图像选择器 UI 和拍摄的图像都处于纵向模式。我怎样才能解决这个问题 ?
【问题讨论】:
你是否正在以任何方式修改picker.view.transform? 不,我不是。但我正在为我的项目使用 Cocos2D 模板。您认为这可能会以某种方式导致问题吗? 【参考方案1】:你需要做三件事:
-
告诉 viewController 只展示 imagePicker
支持纵向。
告诉 imagePicker 不要旋转实时摄像机源。
取消旋转捕获的图像。
imagePicker 直接接收设备方向更改的通知。为了防止实时摄像头随设备旋转,您可以通过告诉 UIDevice endGenerating 在 imagePicker 显示后的方向通知来阻止它接收这些通知:
while ([currentDevice isGeneratingDeviceOrientationNotifications])
[currentDevice endGeneratingDeviceOrientationNotifications];
之所以把它放在一个循环中是因为imagePicker开始GeneratingDeviceOrientationNotifications,然后在它被关闭时结束它,使普通设备上的通知计数从1到2回到1。
imagePicker 关闭后,可以调用:
while (![currentDevice isGeneratingDeviceOrientationNotifications])
[currentDevice beginGeneratingDeviceOrientationNotifications];
以便您的 ViewController 可以继续接收方向更改通知。
不幸的是,即使关闭此功能,图像仍会以正确的图像方向保存,因此在保存图像或对其进行任何操作之前,您必须通过以下方式删除应用的方向转换手动反击:
-(UIImage *)turnMeAround:(UIImage *)image
CGAffineTransform transform = CGAffineTransformIdentity;
CGFloat scale = [[UIScreen mainScreen] scale]; //retina
CGSize size = CGSizeMake(image.size.width*scale,image.size.height*scale);
switch (image.imageOrientation)
case UIImageOrientationUp:
return image;
case UIImageOrientationDown:
size = CGSizeMake(size.height,size.width);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationLeft:
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
case UIImageOrientationRight:
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage));
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, CGRectMake(0,0,size.width,size.height), image.CGImage);
CGImageRef ref = CGBitmapContextCreateImage(context);
UIImage *upsideRight = [UIImage imageWithCGImage:ref];
CGContextRelease(context);
CGImageRelease(ref);
return upsideRight;
【讨论】:
【参考方案2】:非常感谢大家的帮助,但对我有用的方法如下:
所以我发现罪魁祸首是 Xcode 的 Cocos2D 模板。它在 RootViewController 中生成了以下代码:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
//
// There are 2 ways to support auto-rotation:
// - The OpenGL / cocos2d way
// - Faster, but doesn't rotate the UIKit objects
// - The ViewController way
// - A bit slower, but the UiKit objects are placed in the right place
//
#if GAME_AUTOROTATION==kGameAutorotationNone
//
// EAGLView won't be autorotated.
// Since this method should return YES in at least 1 orientation,
// we return YES only in the Portrait orientation
//
return ( interfaceOrientation == UIInterfaceOrientationPortrait );
#elif GAME_AUTOROTATION==kGameAutorotationCCDirector
//
// EAGLView will be rotated by cocos2d
//
// Sample: Autorotate only in landscape mode
//
if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft )
[[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeRight];
else if( interfaceOrientation == UIInterfaceOrientationLandscapeRight)
[[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeLeft];
// Since this method should return YES in at least 1 orientation,
// we return YES only in the Portrait orientation
return ( interfaceOrientation == UIInterfaceOrientationPortrait );
#elif GAME_AUTOROTATION == kGameAutorotationUIViewController
//
// EAGLView will be rotated by the UIViewController
//
// Sample: Autorotate only in landscpe mode
//
// return YES for the supported orientations
return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );
#else
#error Unknown value in GAME_AUTOROTATION
#endif // GAME_AUTOROTATION
// Shold not happen
return NO;
在上面的代码中我改变了这个:
return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );
对此:
return ( UIInterfaceOrientationIsPortrait( interfaceOrientation ) );
这样就解决了。
【讨论】:
以上是关于在 iPad 上以纵向模式启动图像选择器的主要内容,如果未能解决你的问题,请参考以下文章
在 iPad 上以横向启动后,iphone 应用程序没有响应
LaunchScreen.storyboard 中 iPad 启动画面的不同背景图像,用于横向和纵向模式