检测iOS UIDevice方向

时间:2012-02-03 00:35:33

标签: ios objective-c swift orientation uidevice

我需要检测设备何时处于纵向方向,以便我可以触发特殊动画。但我不希望我的观点自动旋转。

当设备旋转为纵向时,如何覆盖自动旋转视图?我的应用程序只需要在横向上显示它的视图,但如果我想能够检测到旋转到肖像,我似乎还需要支持肖像。

9 个答案:

答案 0 :(得分:169)

在加载应用程序或加载视图时尝试执行以下操作:

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

然后添加以下方法:

- (void) orientationChanged:(NSNotification *)note
{
   UIDevice * device = note.object;
   switch(device.orientation)
   {
       case UIDeviceOrientationPortrait:
       /* start special animation */
       break;

       case UIDeviceOrientationPortraitUpsideDown:
       /* start special animation */
       break;

       default:
       break;
   };
}

以上内容可让您注册设备的方向更改,而无需启用视图的自动旋转。


注意

在iOS的所有情况下,当你添加一个观察者时,也要在适当的时候删除它(当视图出现/消失时,可能会,但并非总是如此)。您只能拥有观察/取消观察代码的“对”。如果你不这样做,应用程序将崩溃。选择观察/不观察的位置超出了本质量保证的范围。但是,你必须有一个“unobserve”来匹配上面的“观察”代码。

答案 1 :(得分:15)

如果你想到这个问题来寻找如何检测方向变化(不一定要禁用旋转),你也应该知道{8}可以从iOS 8获得。

来自viewWillTransitionToSize

的Swift示例
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in

        let orient = UIApplication.sharedApplication().statusBarOrientation

        switch orient {
        case .Portrait:
            println("Portrait")
            // Do something
        default:
            println("Anything But Portrait")
            // Do something else
        }

        }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
            println("rotation completed")
    })

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}

如果你不需要担心实际的方向:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    // do something

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}

来自here

的Objective-C示例
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{   
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
    {
        UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
        // do whatever
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
    { 

    }];

    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}

如果您不需要担心实际方向(取自here):

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    // Do view manipulation here.
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}

另见

答案 2 :(得分:3)

1)大卫答案的快速版本 2)如果你仍然想要在没有方向改变的情况下检测方向(Moe对于How Do I detect the orientation of the device on iOS?的答案的快速展开)

    // Initial device orientation
    let orientation: UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
    if(orientation == UIInterfaceOrientation.Unknown){
        // code for Unknown
    }
    else if(orientation == UIInterfaceOrientation.Portrait){
        // code for Portrait
    }
    else if(orientation == UIInterfaceOrientation.PortraitUpsideDown){
        // code for Portrait
    }
    else if(orientation == UIInterfaceOrientation.LandscapeRight){
        // code for Landscape        
    }
    else if(orientation == UIInterfaceOrientation.LandscapeLeft){
        // ode for Landscape
    }

    // To detect device orientation change
    UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()
    NSNotificationCenter.defaultCenter().addObserver(
        self,
        selector: "orientationChanged:",
        name: UIDeviceOrientationDidChangeNotification,
        object: UIDevice.currentDevice())

orientationChanged函数

func orientationChanged(note: NSNotification)
{
    let device: UIDevice = note.object as! UIDevice
    switch(device.orientation)
    {
        case UIDeviceOrientation.Portrait:
        // code for Portrait
        break
        case UIDeviceOrientation.PortraitUpsideDown:
        // code for Portrait
        break
        case UIDeviceOrientation.LandscapeLeft:
        // code for Landscape
        break
        case UIDeviceOrientation.LandscapeRight:
        // code for Landscape
        break
        case UIDeviceOrientation.Unknown:
        // code for Unknown
        break
        default:
        break
    }
}

答案 3 :(得分:1)

如果我理解正确,您的应用只是风景。您只需在应用程序设置中指定它仅为横向,因此无需担心轮换。无论iPad如何定位,该应用程序都将以横向开始并停留在那里。

答案 4 :(得分:0)

首先禁用除所需方向以外的所有方向(以便它不旋转)

然后像大卫说的那样只是让设备当前定位:

https://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MotionEvents/MotionEvents.html

或者你也可以自己使用加速度计(因为无论如何都要这样做) 并检查重力在哪里,看看它有什么方向。如果采用这种方法,您可以自己使用这些值来获得不同的结果。

答案 5 :(得分:0)

如果您不想创建设备对象,也可以使用

-(void) seObserverForOrientationChanging
{
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter]
     addObserver:self selector:@selector(orientationChanged:)
     name:UIDeviceOrientationDidChangeNotification
     object:[UIDevice currentDevice]];
}


- (void) orientationChanged:(NSNotification *)note
{
    if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){
        //Do something in landscape
    }
    else {
        //Do something in portrait
    }
}

答案 6 :(得分:0)

即使设备没有旋转,也会在iphone上多次调用

.UIDeviceOrientationDidChange通知。不知道原因,但如果只在设备真正旋转时需要它,请执行以下操作。

NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: .UIDeviceOrientationDidChange, object: nil)

从observer调用的方法应如下所示:

func orientationChanged() {

    if traitCollection.isIphone {

        defer {
            self.previousTraitCollectionForIphone = traitCollection
        }

        guard let previousTraitCollectionForIphone = previousTraitCollectionForIphone else {

            updateView()
            return
        }

        if previousTraitCollectionForIphone != traitCollection {
            updateView()
        }

    } else {
        updateView()
    }
}

答案 7 :(得分:0)

在Swift 5.0中。

设备方向与屏幕尺寸还是StatusBar.isLandscape?

如果要检测背景方向的变化,并且还需要检测面朝上/朝下的变化,请检查此链接In Swift, how to get the device orientation correctly right after it's launched?

它介绍了如何使用3种替代方法在Swift中正确检测方向: -viewWillTransitionToSize() -使用观察者 -使用状态栏

答案 8 :(得分:0)

这里是一些额外的代码,以避免虚假的 UI 重置或转换:

- (void) orientationChanged:(NSNotification *)note
{
    UIDeviceOrientation newOrientation = ((UIDevice*)note.object).orientation;
    
    // don't do anything if device is flat...
    if (UIDeviceOrientationIsFlat(newOrientation) || newOrientation == UIDeviceOrientationUnknown)
        return;
           
    // ... and only if orientation has changed
    if (newOrientation != self->lastOrientation) {
        // do whatever you need to do to change UI
        
        self->lastOrientation = newOrientation;
    }
}