【问题标题】:Launching Image Picker in Portrait Mode on iPad在 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 模板。您认为这可能会以某种方式导致问题吗?

标签: objective-c ios xcode ipad


【解决方案1】:

你需要做三件事:

  1. 告诉 viewController 只展示 imagePicker 支持纵向。
  2. 告诉 imagePicker 不要旋转实时摄像机源。
  3. 取消旋转捕获的图像。

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

    这样就解决了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多