繁体   English   中英

检测 iOS UIDevice 方向

[英]Detecting iOS UIDevice orientation

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

当设备旋转到纵向时,如何覆盖自动旋转的视图? 我的应用程序只需要以横向方式显示它的视图,但如果我希望能够检测到纵向的旋转,我似乎也需要支持纵向。

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

[[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”来匹配上面的“observe”代码。

如果您遇到这个问题是为了寻找如何检测方向变化(不一定要禁用旋转),您还应该了解 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)
}

来自此处的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];
}

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

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

也可以看看

1) David 答案的 Swift 版本 2) 如果您仍然想在没有方向变化的情况下检测方向(Moe 对如何在 iOS 上检测设备方向的回答的 Swift 版本?

    // 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())

方向改变函数

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
    }
}

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

-(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
    }
}

如果我理解正确,您的应用程序仅适用于横向。 您可以简单地在应用程序设置中指定它仅为横向,因此无需担心旋转。 无论 iPad 的方向如何,该应用程序都将以横向模式启动并停留在那里。

即使设备没有旋转, .UIDeviceOrientationDidChange通知也会在 iphone 上多次调用。 不知道原因,但如果您仅在设备真正旋转时才需要它,请执行以下操作。

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

从观察者调用的方法应该是这样的:

func orientationChanged() {

    if traitCollection.isIphone {

        defer {
            self.previousTraitCollectionForIphone = traitCollection
        }

        guard let previousTraitCollectionForIphone = previousTraitCollectionForIphone else {

            updateView()
            return
        }

        if previousTraitCollectionForIphone != traitCollection {
            updateView()
        }

    } else {
        updateView()
    }
}

在 Swift 5.0 中。

DeviceOrientation vs. ScreenSize vs StatusBar.isLandscape?

如果您想检测背景中的方向变化,并且还需要检测面朝上/朝下的变化,请检查此链接在 Swift 中,如何在启动后立即正确获取设备方向?

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

下面是一些额外的代码,以避免虚假的 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;
    }
}

首先禁用除您想要的方向之外的所有方向(以便它不会旋转)

然后就像大卫说的那样获取设备当前的方向:

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

或者,您可以自己使用加速度计(因为它是如何完成的)并检查重力的位置以查看它的方向。 如果您采用这种方法,您可以自己处理这些值以获得不同的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM