2

我想呈现一个响应方向变化的视图,但由于各种原因不能使用 iOS 的内置自动旋转。在viewDidLoad我使用当前方向来确定视图的初始布局:

_originalOrientation = [UIDevice currentDevice].orientation;

// if we were launched flat or unknown, use the status bar orientation as a guide
if (_originalOrientation == UIDeviceOrientationUnknown ||
    _originalOrientation == UIDeviceOrientationFaceDown ||
    _originalOrientation == UIDeviceOrientationFaceUp) {

        _originalOrientation = UIDeviceOrientationFromInterfaceOrientation([UIApplication sharedApplication].statusBarOrientation);
}

正如您从我的评论中看到的那样,我需要处理[UIDevice currentDevice].orientation不是可用方向的情况(即设备是平的或处于未知方向)。在这种情况下,我尝试使用statusBarOrientation来推断设备的方向(使用UIViewController'sinterfaceOrientation将是获取相同信息的另一种方法):

UIDeviceOrientation UIDeviceOrientationFromInterfaceOrientation(UIInterfaceOrientation interface) {
    // note: because UIInterfaceOrientationLandscapeLeft and UIInterfaceOrientationLandscapeRight have the same value, this conversion can't distinguish them

    if (interface == UIInterfaceOrientationLandscapeLeft) {
        return UIDeviceOrientationLandscapeLeft;

    } else if (interface == UIInterfaceOrientationLandscapeRight) {
        return UIDeviceOrientationLandscapeRight;

    } else if (interface == UIInterfaceOrientationPortraitUpsideDown) {
        return UIDeviceOrientationPortraitUpsideDown;

    } else {
        return UIDeviceOrientationPortrait;
    }
}

但是我的逻辑无法准确辨别这两种景观情况,因为它们被定义UIApplication.h相同的常数值:

// Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
// This is because rotating the device to the left requires rotating the content to the right.
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
    UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
    UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
    UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
    UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
};

有没有另一种方法可以区分UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRight?除了使用状态栏方向之外,我还有更好的方法来执行我的“后备”逻辑吗?

4

6 回答 6

3

UIDevice 的方向属性是一个枚举,它可以区分左右横向(它们的值分别为 3 和 4),因此您可以检查该值。

typedef enum {
   UIDeviceOrientationUnknown,
   UIDeviceOrientationPortrait,
   UIDeviceOrientationPortraitUpsideDown,
   UIDeviceOrientationLandscapeLeft,
   UIDeviceOrientationLandscapeRight,
   UIDeviceOrientationFaceUp,
   UIDeviceOrientationFaceDown
} UIDeviceOrientation;
于 2013-04-14T05:42:33.057 回答
3

你写了:

但是我的逻辑无法准确辨别这两种情况,因为它们被定义为 UIApplication.h 是相同的常量值

我很确定他们不是!界面和设备方向的值被交换。见UIApplication.h

typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
    UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
    UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
    UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
    UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
};

界面方向 UIInterfaceOrientationLandscapeLeft等于设备方向UIDeviceOrientationLandscapeRight反之亦然。但:

  • UIInterfaceOrientationLandscapeLeft != UIInterfaceOrientationLandscapeRight
  • UIDeviceOrientationLandscapeLeft != UIDeviceOrientationLandscapeRight

试试这个代码,我认为这将解决问题:

UIDeviceOrientation UIDeviceOrientationFromInterfaceOrientation(UIInterfaceOrientation interface) {
    // interface orientation left is device orientation right
    if (interface == UIInterfaceOrientationLandscapeLeft) {
        return UIDeviceOrientationLandscapeRight;

    // interface orientation right is device orientation left
    } else if (interface == UIInterfaceOrientationLandscapeRight) {
        return UIDeviceOrientationLandscapeLeft;

    } else if (interface == UIInterfaceOrientationPortraitUpsideDown) {
        return UIDeviceOrientationPortraitUpsideDown;

    } else {
        return UIDeviceOrientationPortrait;
    }
}

顺便说一句,您还应该考虑为您的函数使用自己的前缀而不是UI,否则可能很容易错误地认为这UIDeviceOrientationFromInterfaceOrientation是一个 API 函数。

于 2013-04-22T14:56:11.637 回答
0

如果您要显示相机所看到的内容,我会忽略所有方向并向用户显示设备在纵向中看到的内容的预览。他们看到的永远是“正确的”,绝不会意外地颠倒过来。

于 2013-04-18T21:38:47.383 回答
0

gravity您始终可以使用类的属性来确定设备方向CMDeviceMotion。属性返回指向地球中心的归一化矢量(也称为真实重力矢量)。如果您对角度不感兴趣,您可以只测试符号并为您的目的生成常量。

于 2013-04-19T07:01:40.330 回答
0

这就是我在通行证中的做法

创建一个名为 previousOr 的全局变量。然后在您的第一个 viewController 中使用以下代码来确定状态栏的位置。我把它放在 viewDidAppear

if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) {
    previousOr = [NSString stringWithFormat:@"L"];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) {
    previousOr = [NSString stringWithFormat:@"L"];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) {
    previousOr = [NSString stringWithFormat:@"P"];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown) {
    previousOr = [NSString stringWithFormat:@"P"];
}

然后在您随后的 viewControllers 中,您在 ViewDidLoad 方法中有以下内容,这将检测设备是纵向还是横向,或者设备是否是平的,设备在平放之前是什么:

if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
    NSLog(@"landscape");
    [self switchToLandscape];
}
else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
    NSLog(@"portrait");
    [self switchToPortrait];
}
else {
    if ([previousOr isEqualToString:@"L"]) {
        [self switchToLandscape];
    }
    else  {
        [self switchToPortrait];
    }
}

然后您还可以执行以下操作来重新绘制视图上的元素

- (void)switchToLandscape {
    previousOr = [NSString stringWithFormat:@"L"];
    //do stuff like replot centers
}

- (void)switchToPortrait {
    previousOr = [NSString stringWithFormat:@"P"];
    //do stuff like replot centers
}

然后您还可以通过以下方式检测方向的变化:

- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) {
    [self switchToLandscape];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) {
    [self switchToLandscape];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) {
    [self switchToPortrait];
}
else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown) {
    [self switchToPortrait];
}
}

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

-(BOOL) shouldAutorotate {
    return YES;
}

笔记; 我同时放入了 shouldAutorotateToInterfaceOrientation 和 shouldAutoRotate 以实现向后兼容性。

于 2013-04-22T21:20:22.783 回答
0

曾经面临同样的问题。这是答案,总是去 UIIntefaceOrientation 检查当前方向是横向还是纵向。

目标 C:

if([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationLandscapeRight)
 {
         //Go Here for landscape
 }
    else if ([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortraitUpsideDown)
 {
        //Go Here for Portrait

 }

斯威夫特:

let currentOrient : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
if currentOrient == UIInterfaceOrientation.landscapeLeft || currentOrient == UIInterfaceOrientation.landscapeRight
 {
            //Go Here for landscape
 }
else if currentOrient == UIInterfaceOrientation.portrait || currentOrient == UIInterfaceOrientation.portraitUpsideDown
 {
            //Go Here for Portrait
 }
于 2018-11-17T10:51:13.407 回答