首页 文章

如何在iOS 7中以编程方式设置设备方向?

提问于
浏览
70

我正在使用AutoLayout在iPad应用程序上工作,如果用户启用某种模式(“抬头”模式),我想只支持纵向(或纵向颠倒)方向,此外,如果设备在风景,我想自动切换到纵向模式 .

在顶视图控制器中,我有以下内容:

- (NSUInteger) supportedInterfaceOrientations {
    if (self.modeHeadsUp) {
        return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
    } else {
        return UIInterfaceOrientationMaskAll;
    }
}

- (BOOL) shouldAutorotate {
    return TRUE;
}

基于我在其他地方看到的答案,答案似乎是我应该使用"application setStatusBarOrientation" . 因此,在用户选择"heads-up"模式的方法中,我包括:

UIApplication *application = [UIApplication sharedApplication];
    [application setStatusBarOrientation:UIInterfaceOrientationPortrait
                                animated:YES];

但是,这根本就没有做任何事情 . 虽然我可以物理移动设备以使其旋转为纵向,但它不会自动移动 .

实际上,在运行上面的代码后尝试以横向模式尝试以编程方式设置方向时,当我使用以下代码查询应用程序“statusBarOrientation”时,它对于横向保持为“4”:

UIApplication *application = [UIApplication sharedApplication];
int orientation = [application statusBarOrientation];
self.movesTextView.text = [NSString stringWithFormat:@"ORIENTATION %d", orientation];

好像autolayout可能没有被setStatusBarOrientation触发,所以我试图在之后添加这个代码,没有效果:

[super updateViewConstraints];
    [self.view updateConstraints];

我意识到Apple希望将设备方向放在用户手中 . 但是,我希望能够在不进行“抬头”模式时支持横向模式 .

我错过了能够强制改变方向的东西吗?

16 回答

  • 1

    我遇到的问题与你相似 . 我需要锁定某些屏幕的设备方向(如Login)并允许其他屏幕旋转 .

    经过一些更改并在下面得到一些答案后,我通过以下方式完成了

    • 在项目的Info.plist中启用所有方向 .

    enter image description here

    • 禁用其中的方向ViewControllers,我需要设备不要旋转,就像在我的情况下登录屏幕 . 我需要在这个VC中覆盖 shouldAutorotate 方法:

    -(BOOL)shouldAutorotate{ return NO; }

    希望这对你有用 .

  • 2

    这是iOS 7,8,9,10的完整工作示例如何将应用方向更改为当前相反的方向

    Objective-C

    - (void)flipOrientation
    {
        NSNumber *value;
        UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
        if(UIInterfaceOrientationIsPortrait(currentOrientation))
        {
            if(currentOrientation == UIInterfaceOrientationPortrait)
            {
                value = [NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown];
            }
            else //if(currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
            {
                value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
            }
        }
        else
        {
            if(currentOrientation == UIInterfaceOrientationLandscapeRight)
            {
                value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
            }
            else //if(currentOrientation == UIInterfaceOrientationLandscapeLeft)
            {
                value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
            }
        }
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
        [UIViewController attemptRotationToDeviceOrientation];
    }
    

    Swift 3

    func flipOrientation() -> Void
    {
        let currentOrientation : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
        var value : Int = 0;
        if(UIInterfaceOrientationIsPortrait(currentOrientation))
        {
            if(currentOrientation == UIInterfaceOrientation.portrait)
            {
                value = UIInterfaceOrientation.portraitUpsideDown.rawValue
            }
            else //if(currentOrientation == UIInterfaceOrientation.portraitUpsideDown)
            {
                value = UIInterfaceOrientation.portrait.rawValue
            }
        }
        else
        {
            if(currentOrientation == UIInterfaceOrientation.landscapeRight)
            {
                value = UIInterfaceOrientation.landscapeLeft.rawValue
            }
            else //if(currentOrientation == UIInterfaceOrientation.landscapeLeft)
            {
                value = UIInterfaceOrientation.landscapeRight.rawValue
            }
        }
        UIDevice.current.setValue(value, forKey: "orientation")
        UIViewController.attemptRotationToDeviceOrientation()
    }
    
  • 4

    对于iOS 7和8:

    Objective-C的:

    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    

    斯威夫特3:

    let value = UIInterfaceOrientation.landscapeLeft.rawValue
    UIDevice.current.setValue(value, forKey: "orientation")
    

    我在 - viewDidAppear: 中称呼它 .

  • 2

    用这个 . 定位问题的完美解决方案..更早和更早

    [[UIDevice currentDevice] setValue:
        [NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
            forKey:@"orientation"];
    
  • 10

    当条件发生变化时,您需要调用attemptRotationToDeviceOrientation (UIViewController)使系统调用 supportedInterfaceOrientations .

  • 4

    这对我有用 Xcode 6&5 .

    - (BOOL)shouldAutorotate {
        return YES;
    }
    - (NSUInteger)supportedInterfaceOrientations {
        return (UIInterfaceOrientationMaskPortrait);
    }
    
  • 3

    请尝试使用您的代码 .

    -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
    
    -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    

    一旦用户选择任何选项,然后调用此方法,因为用户可以处于横向模式,然后他可以在同一个视图控制器中只设置纵向模式,因此自动视图应该移动到纵向模式,以便在该按钮中调用此方法

    -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    
  • 0
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    

    确实有效但您必须在视图控制器中返回shouldAutorotate并带YES

    - (BOOL)shouldAutorotate
    {
        return self.shouldAutoRotate;
    }
    

    但是如果你这样做,你的VC会在用户旋转设备时自动旋转...所以我把它改为:

    @property (nonatomic, assign) BOOL shouldAutoRotate;
    
    - (BOOL)shouldAutorotate
    {
        return self.shouldAutoRotate;
    }
    

    我打电话给

    - (void)swithInterfaceOrientation:(UIInterfaceOrientation)orientation
    {
        self.rootVC.shouldAutoRotate = YES;
    
        NSNumber *value = [NSNumber numberWithInt: orientation];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
    

    通过按钮单击强制新方向 . 要将shouldAutoRotate设置为NO,我将添加到rootVC中

    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
    {
        self.shouldAutoRotate = NO;
    }
    

    PS:此解决方法也适用于所有模拟器 .

  • 1

    对我有用的唯一方法是呈现虚拟模态视图控制器 .

    UIViewController* dummyVC = [[UIViewController alloc] init];
    dummyVC.view = [[UIView alloc] init];
    [self presentModalViewController:dummyVC animated:NO];
    [self dismissModalViewControllerAnimated:NO];
    

    当取消模态视图控制器时,将要求VC更新接口方向 .

    奇怪的是,当推送/弹出具有不同支持的接口方向的子视图控制器时,UINavigationController正是这样做的(在iOS 6.1,7.0上测试过) .

  • 2

    此解决方案允许您通过暂时覆盖 UIDevice.current.orientation 的值然后要求系统旋转接口以匹配设备的旋转来强制某个接口方向:

    Important: This is a hack, and could stop working at any moment

    在应用程序的根视图控制器中添加以下内容:

    class RootViewController : UIViewController {
        private var _interfaceOrientation: UIInterfaceOrientation = .portrait
        override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask(from: _interfaceOrientation) }
        override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return _interfaceOrientation }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Register for notifications
            NotificationCenter.default.addObserver(self, selector: #selector(RootViewController.handleInterfaceOrientationChangeRequestedNotification(_:)), name: .interfaceOrientationChangeRequested, object: nil)
        }
    
        deinit { NotificationCenter.default.removeObserver(self) }
    
        func handleInterfaceOrientationChangeRequestedNotification(_ notification: Notification) {
            guard let interfaceOrientation = notification.object as? UIInterfaceOrientation else { return }
            _interfaceOrientation = interfaceOrientation
            // Set device orientation
            // Important:
            // • Passing a UIDeviceOrientation here doesn't work, but passing a UIInterfaceOrientation does
            // • This is a hack, and could stop working at any moment
            UIDevice.current.setValue(interfaceOrientation.rawValue, forKey: "orientation")
            // Rotate the interface to the device orientation we just set
            UIViewController.attemptRotationToDeviceOrientation()
        }
    }
    
    private extension UIInterfaceOrientationMask {
    
        init(from interfaceOrientation: UIInterfaceOrientation) {
            switch interfaceOrientation {
            case .portrait: self = .portrait
            case .landscapeLeft: self = .landscapeLeft
            case .landscapeRight: self = .landscapeRight
            case .portraitUpsideDown: self = .portraitUpsideDown
            case .unknown: self = .portrait
            }
        }
    }
    
    extension Notification.Name {
        static let interfaceOrientationChangeRequested = Notification.Name(rawValue: "interfaceOrientationChangeRequested")
    }
    

    确保在“部署信息”下检查所有接口方向:

    Interface Orientations

    请求界面方向在您需要的地方更改:

    NotificationCenter.default.post(name: .interfaceOrientationChangeRequested, object: UIInterfaceOrientation.landscapeRight)
    
  • 1

    如果您想将应用程序的主视图锁定为纵向,但想要在横向中打开弹出视图,并且您正在使用tabBarController作为rootViewController,则可以在AppDelegate上使用此代码 .

    AppDelegate.h

    @interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    @property (strong, nonatomic) UITabBarController *tabBarController;
    
    @end
    

    AppDelegate.m

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
        // Create a tab bar and set it as root view for the application
        self.tabBarController = [[UITabBarController alloc] init];
        self.tabBarController.delegate = self;
        self.window.rootViewController = self.tabBarController;
    
        ...
    }
    
    - (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController
    {
        return UIInterfaceOrientationMaskPortrait;
    }
    
    - (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController
    {
        return UIInterfaceOrientationPortrait;
    }
    

    它工作得很好 .

    在viewController中,您希望以横向显示,只需使用以下内容:

    - (NSUInteger)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskLandscape;
    }
    
    - (BOOL)shouldAutorotate {
        return YES;
    }
    
  • 0
    • 将此语句添加到 AppDelegate.h
    //whether to allow cross screen marker 
    @property (nonatomic, assign) allowRotation BOOL;
    
    • 将此段代码写入 AppDelegate.m
    - (UIInterfaceOrientationMask) application: (UIApplication *) supportedInterfaceOrientationsForWindow: application (UIWindow *) window {
        If (self.allowRotation) {
            UIInterfaceOrientationMaskAll return;
        }
        UIInterfaceOrientationMaskPortrait return;
    }
    
    • 更改委托应用的 allowRotation 属性
  • 1

    如果你有一个应该保持在纵向模式的UIViewController,只需添加这个覆盖就可以了 .

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
    

    最好的部分是在显示此视图时没有动画,它刚刚处于正确的方向 .

  • 3

    基础UINavigationController应具有以下回调,以便子项可以决定他们想要的方向 .

    -(NSUInteger)supportedInterfaceOrientations {
        UIViewController *topVC = self.topViewController;
        return topVC.supportedInterfaceOrientations;
    }
    
    -(BOOL)shouldAutorotate {
       UIViewController *topVC = self.topViewController;
       return [topVC shouldAutorotate];
    }
    
  • 190

    如果您只想要纵向模式,在iOS 9(Xcode 7)中,您可以:

    • 转到Info.plist

    • 选择"Supported interface orientations"项目

    • 删除"Landscape(left home button)"和"Landscape(right home button)"

    enter image description here

  • 20

    这对我很有帮助....

    NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    

相关问题