13

您好我需要禁用 UIImagePicker 的旋转。
如果用户在 iPhone 处于“横向”模式时拍照,按钮将旋转,并且所拍摄的照片也会旋转。我想禁用该选项,因此加速度计将无法工作,并且它总是会像在纵向模式下一样拍照。
我怎样才能做到这一点?
谢谢,马坦拉多姆斯基。

4

4 回答 4

28

这是解决方案:[UIDevice endGeneratingDeviceOrientationNotifications]

为什么这么难找?两个原因:

  1. 记录打开或关闭方向通知的UIDevice次数。如果开启次数多于关闭次数,仍会发出通知。
  2. 显示UIImagePickerController这些通知时会打开这些通知。

因此,调用此方法一次对图像选择器没有任何作用。为了确保方向通知关闭并保持关闭,您需要在选择器出现之前和之后将它们关闭。

这不会影响 iOS 或其他应用程序。它甚至不会完全影响您自己的应用程序:与我建议的其他方法一样,相机按钮会继续响应方向变化,并且拍摄的照片也可以感知方向。这很奇怪,因为如果不需要,设备方向硬件应该被关闭。

@try 
{
    // Create a UIImagePicker in camera mode.
    UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease]; 
    picker.sourceType = UIImagePickerControllerSourceTypeCamera;  
    picker.delegate = self; 

    // Prevent the image picker learning about orientation changes by preventing the device from reporting them.
    UIDevice *currentDevice = [UIDevice currentDevice];

    // The device keeps count of orientation requests.  If the count is more than one, it continues detecting them and sending notifications.  So, switch them off repeatedly until the count reaches zero and they are genuinely off.
    // If orientation notifications are on when the view is presented, it may slide on in landscape mode even if the app is entirely portrait.
    // If other parts of the app require orientation notifications, the number "end" messages sent should be counted.  An equal number of "begin" messages should be sent after the image picker ends.
    while ([currentDevice isGeneratingDeviceOrientationNotifications])
        [currentDevice endGeneratingDeviceOrientationNotifications];

    // Display the camera.
    [self presentModalViewController:picker animated:YES];

    // The UIImagePickerController switches on notifications AGAIN when it is presented, so switch them off again.
    while ([currentDevice isGeneratingDeviceOrientationNotifications])
        [currentDevice endGeneratingDeviceOrientationNotifications];
}
@catch (NSException *exception) 
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No Camera" message:@"Camera is not available" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
    [alert show];
    [alert release];
}

如上所述,拍摄的照片可能仍处于错误的方向。如果您希望它们的方向一致,请检查它们的纵横比并相应地旋转。我建议如何将 UIImage 旋转 90 度?

//assume that the image is loaded in landscape mode from disk
UIImage * landscapeImage = [UIImage imageNamed: imgname];
UIImage * portraitImage = [[UIImage alloc] initWithCGImage: landscapeImage.CGImage scale:1.0 orientation: UIImageOrientationLeft] autorelease];
于 2012-04-15T10:39:46.457 回答
3

Back in 2010, How to prevent a modal UIImagePickerController from rotating? found no happy answer to this question.

I found an alternative, but it's also like to get you rejected from the App Store: remove all observers from the window.

If some part of your app outside a viewController needs orientation change messages, it can register for them:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];

The window, not surprisingly, registers for such notifications, then rotates the view controllers if they accept the new orientation. It's not conveniently watching for UIDeviceOrientationDidChangeNotification, so there must be a privately named equivalent. All you can do is remove every notification from the window:

[[NSNotificationCenter defaultCenter] removeObserver:[[self view] window]];

There is no restoring this, if you just wanted to temporarily suppress orientation changes. Neither can we tell if the window was watching for any important notifications from other sources. It's incomplete, too - the button for turning over, and the button for taking a photo, move and rotate on their own.

Screenshot of iPad in landscape mode with camera UI still in portrait

How can you fix that quirk? You could switch off showsCameraControls on the UIImagePicker, and provide your own cameraOverlayView with the camera buttons on it. Or continue randomly removing notifications by traversing an entire view hierarchy (also rejection material) removing notifications from everything:

- (void) removeAllNotificationsFromView:(UIView*) view;
{
    // This recurses through the view hierarchy removing all notifications for everything.
    // This is potentially destructive, and may result in rejection from the App Store.
    [[NSNotificationCenter defaultCenter] removeObserver:view];
    for (UIView *subview in [view subviews])
        [self removeAllNotificationsFromView:subview];
}

[self removeAllNotificationsFromView:imagePicker.view];

I don't recommend using this, but it provides some interesting insights into how orientation changes are detected and propagated.

于 2012-04-13T13:42:19.420 回答
1

以上解决方案都不适合我。这是什么工作(对于我已经测试过的iOS 7)-

  1. 子类UIImagePickerController

  2. 覆盖shouldAutorotate方法并返回NO

    -(BOOL)shouldAutorotate
    {
        return NO;
    }
于 2014-05-02T02:49:15.337 回答
-3

将以下代码添加到您的视图中

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{
     return NO;
}
于 2012-04-09T13:26:52.070 回答