在横屏模式下使用UIImagePickerController

32

我正在创建一个横屏模式的应用程序,并使用UIImagePickerController在其中使用iPhone相机拍照,我也希望将其创建为横屏模式。

但是,正如苹果文档所建议的那样,UIImagePickerController不支持横向方向,那么我该怎么做才能获得所需的功能?


它似乎在iOS 8 beta 4中可以工作。唯一的问题是,在拍照后,它会在纵向模式下显示屏幕(使用此照片或取消)。但横向拍摄的图像很好。 - Lim Thye Chean
9个回答

47

如果您想在横向模式下使用UIImagePickerController,请使用user1673099的答案,但是不要使用:

- (BOOL)shouldAutorotate
{
    return NO;
}

使用:

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}

然后选择器会以横屏模式打开:

enter image description here

但请确保在部署信息中勾选“纵向”:

enter image description here


它运行得很好。有一个问题,为什么我们在部署信息中要检查纵向模式?我知道这是必要的,但我无法理解原因。 - Anson Yao
2
@AnsonYao 因为 UIImagePickerController 只支持竖屏模式。如果你不在全局范围内支持竖屏,图像选择器将会崩溃,因为它没有可用的方向。 - pkamb
@Mc.Lover 如果我在部署信息中选择“纵向模式”,它就能够工作。但是它会改变整个应用程序的方向。请问您能告诉我如何解决这个问题吗? - shaqir saiyed
@shaqirsaiyed 添加: 覆盖功能shouldAutorotate() -> Bool { 如果(UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft || UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight){ 返回真 } 其他 { return false; } } 覆盖功能supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 返回[UIInterfaceOrientationMask.Landscape] } 对于任何应该只处于横向模式的视图控制器。 - vtcajones
此外,如果您想支持横屏和竖屏,请使用掩码:UIInterfaceOrientationMaskAllButUpsideDown。 - Matt__C
显示剩余3条评论

34

...而且我也希望在横向模式下创建它。

一行代码可以产生很大的影响!在您的IBAction所在的方法或函数中:

在Swift中,

let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
// .overCurrentContext allows for landscape and portrait mode
imagePickerController.modalPresentationStyle = .overCurrentContext

Objective-C,

->

Objective-C,

UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
[imagePickerController setDelegate:self];
[imagePickerController setModalPresentationStyle: UIModalPresentationOverCurrentContext];

注意:这将允许imagePickerController正确地呈现其视图,但可能不能在呈现时修复旋转问题。


1
这应该是被接受的答案。没有子类化、扩展中的重写或任何其他的黑客技巧,只有简单明了的公共API。 - Nicolas Miari

14

尝试这种方法...

根据苹果文档,图像选择器控制器在横向模式下永远不会旋转。您只能在纵向模式下使用。

要仅为ImagePicker Controller禁用横向模式,请按以下代码操作:

在您的ViewController.m中:

将子类(NonRotatingUIImagePickerController)设为图像选择器控制器

@interface NonRotatingUIImagePickerController : UIImagePickerController

@end

@implementation NonRotatingUIImagePickerController
// Disable Landscape mode.
- (BOOL)shouldAutorotate
{
    return NO;
}
@end

使用方法如下

UIImagePickerController* picker = [[NonRotatingUIImagePickerController alloc] init];
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        picker.delegate = self; 
  etc.... Just as Default ImagePicker Controller

这对我有效,如果你有任何问题,请告诉我。


这对你有帮助吗? - user1673099
我不想禁用横屏模式,我只想在横屏模式下使用图像选择器控制器而不是纵向模式。我想知道是否也可以旋转图像选择器以拍照? - Paras Gorasiya
@ParasGorasiya,ImagePicker永远不会支持横屏模式。它只支持竖屏模式。 - user1673099

9

在 iOS 10/11 中,与 Swift 4.0 配合使用效果非常好。

import UIKit

extension UIImagePickerController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .all
    }
}

只需将扩展名放在项目的某个位置,无需为其子类化即可使用。

如果需要指定设备类型,可以添加以下检查:

import UIKit

extension UIImagePickerController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIDevice.current.userInterfaceIdiom == .phone ? .portrait : .all
    }
}

这将允许iPad自由旋转,但在手机上强制使用纵向模式。只需确保您的应用程序在其info.plist中配置以支持这些功能,否则启动选择器时可能会遇到崩溃。


6

这是一个支持在所有界面方向旋转的版本:

/// Not fully supported by Apple, but works as of iOS 11.
class RotatableUIImagePickerController: UIImagePickerController {

  override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .all
  }
}

这样,如果用户旋转设备,它将更新选择器控制器以支持当前方向。只需像通常实例化UIImagePickerController一样即可。

如果您只想支持子集方向,则可以返回不同的值。


5

在不使用任何hack的情况下,在横向模式下正确使用UIImagePickerController的方法是将其放入UIPopoverController中。

- (void)showPicker:(id)sender
{
    UIButton *button = (UIButton *)sender;
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

    _popover = [[UIPopoverController alloc] initWithContentViewController:picker];
    [_popover presentPopoverFromRect:button.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

2
仅适用于UIUserInterfaceIdiomPad。 - Muruganandham K
1
@yershuachu 对,所以你用另一种方法替换了一个hack?;-) - Ja͢ck
请查看我的答案,这里还有另一个选项:https://dev59.com/lYLba4cB1Zd3GeqPZxvN#34598584 - Dan Rosenstark
谢谢,这是iPad的最佳解决方案。+1 - Alexandre G.
一个UIPopoverController与本地的UIImagePickerController非常不同。 - Carl Smith
显示剩余3条评论

3

修改上述代码的方法

- (NSUInteger)supportedInterfaceOrientations
 {
     UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
     if(orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationLandscapeLeft)
         return UIInterfaceOrientationMaskLandscape;
     else
         return UIInterfaceOrientationMaskPortrait;
 }

2

已经接受的答案对我不起作用。 我还必须将modalPresentationStyle添加到UIImagePickerController中,使其正常工作。

UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
pickerController.modalPresentationStyle = UIModalPresentationCurrentContext; //this will allow the picker to be presented in landscape
pickerController.delegate = self;
pickerController.allowsEditing = YES;
pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:pickerController animated:YES completion:nil];

当然,记得将这个代码放在呈现选择器的控制器中:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape; //this will force landscape
}

但是根据苹果的文档,不支持在横屏模式下显示此选择器,因此请注意。


在代理下如何实现 supportedInterfaceOrientations? - zeus
更准确地说:呈现 UIImagePickerController 的视图控制器应该具有 supportedInterfaceOrientations。在我的示例中,委托是呈现选择器的控制器。我会更新我的答案。 - Michal Cichon

2
如果您正在寻找与此处提到的内容相结合的SwiftUI解决方案,请查看此处。忽略UIImagePickerController representable的安全区域解决了我很多问题。

1
谢谢!这是唯一有效的方法。 :) - Otziii

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