【问题标题】:How to "lock" a view's orientation during device rotation如何在设备旋转期间“锁定”视图的方向
【发布时间】:2014-08-31 12:32:50
【问题描述】:

假设我有一个视图控制器,称之为 ViewControllerPortrait,它被设计为仅以纵向模式显示。例如:

当用户将设备旋转为横向时,我不希望 ViewControllerPortrait 将自身重新定位为横向,但我确实想呈现一个新的全屏视图。我们将全屏视图控制器称为 ViewControllerLandscapeFull。例如:

我最不想看到的是:

我尝试这样做的方法是让窗口的 rootViewController 在获得 willRotateToInterfaceOrientation:duration: 时全屏显示 ViewControllerLandscapeFull

[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[navigationViewController setNavigationBarHidden:YES animated:YES];

self.viewControllerPortrait = [[ViewControllerPortrait alloc] init];
self.viewControllerPortrait.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:self.viewControllerPortrait animated:NO completion:NULL];

然后在 ViewControllerLandscapeFull 我有:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape | UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return (UIInterfaceOrientation)[UIDevice currentDevice].orientation;
}

这很好用。由于 ViewControllerLandscapeFull “更喜欢”风景并且有一个 UIModalPresentationFullScreen modalPresentationStyle,它只会在风景中显示。通过为supportedInterfaceOrientations 返回landscape | portrait,当ViewControllerLandscapeFull 获得willRotateToInterfaceOrientation:duration: 并最终在其上调用dismissViewControllerAnimated:NO 时,允许设备旋转回纵向。

我遇到的唯一问题是,在旋转回纵向期间,您可以暂时看到横向的 ViewControllerPortrait,这就是我要避免的。

ViewControllerPortrait 确实实现了:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

我已经验证 UIKit 正在调用它,但它显然没有任何效果。 (文档说 supportedInterfaceOrientations 只在根视图控制器上调用,并且视图控制器全屏显示,所以我真的很惊讶 UIKit 调用它。)

FWIW,我正在使用 iOS 8 beta 5 SDK 并为 7/8 构建。

非常感谢。

【问题讨论】:

  • 你的应用中有蚂蚁标签栏或导航栏吗?我的意思是您不想旋转的视图控制器是否在任何选项卡栏或导航控制器内?
  • 是的,我上面所说的 ViewControllerPortrait 是 UINavigationController 的一部分(实际上是一个子类)。

标签: ios iphone


【解决方案1】:

我刚开始用 iPhone 编程,但也许这会奏效...

单击您的项目文件 > 部署信息。然后取消单击除肖像以外的所有内容。这样旋转设备不会重新定向。

但是,您仍然可以使用以下方法测试设备是否旋转:

- (BOOL)shouldAutorotate
{
    if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
    {
         NSLog(@"ROTATE to landscape");
         kitty.hidden = NO; 
         //(kitty is my imageview, hidden on load), once the device rotates to landscape, you can show your image.(or you can do something else)
    }
    else{
        NSLog(@"ROTATE to portrait");
        kitty.hidden = YES;
    }
    return YES;
}

【讨论】:

  • 创新的解决方案,但对我来说不太适用。一旦我呈现具有首选横向方向的新视图控制器,ViewControllerPortrait 的 viewWillLayoutSubviews 就会以翻转的边界被调用。我也可以像以前一样在风景中看到它。
【解决方案2】:
houldAutorotate, supportedInterfaceOrientations, preferredInterfaceOrientationForPresentation

如果上述方法位于导航控制器的任何选项卡控制器中,则视图控制器不会调用它们。如果这些方法在 tabbarcontroller 或导航控制器中声明,那么它们将被调用。在我的例子中,viewcontrollers 在navigationcontroller 里面,而navigation controllers 在tabbarcontroller 里面。

为了解决这个问题,我创建了一个类FixedOrientationTab,它是UITabBarController 的子类,以及一个导航类OrientationEnabledNavigation,它是UINavigationController 的子类。然后我在FixedOrientationTabOrientationEnabledNavigation 中实现了shouldAutorotatesupportedInterfaceOrientationspreferredInterfaceOrientationForPresentation 方法。

OrientationEnabledNavigation.h

#import <UIKit/UIKit.h>

@interface OrientationEnabledNavigation : UINavigationController

@end

OrientationEnabledNavigation.m

#import "OrientationEnabledNavigation.h"

@interface OrientationEnabledNavigation ()

@end

@implementation OrientationEnabledNavigation

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (BOOL)shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
//    return NO;
}

- (NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

FixedOrientationTab.h

#import <UIKit/UIKit.h>

@interface FixedOrientationTab : UITabBarController

@end

FixedOrientationTab.m

#import "FixedOrientationTab.h"

@interface FixedOrientationTab ()

@end

@implementation FixedOrientationTab

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (BOOL)shouldAutorotate
{
    return [self.selectedViewController shouldAutorotate];
    //    return NO;
}

- (NSUInteger)supportedInterfaceOrientations
{
    return [self.selectedViewController supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

如果您想在项目中使用导航控制器,请使用OrientationEnabledNavigation 和标签栏FixedOrientationTab。之后,如果您在视图控制器中实现shouldAutorotatesupportedInterfaceOrientationspreferredInterfaceOrientationForPresentation 这些方法,那么它们将被调用。

希望这会有所帮助.. :)

【讨论】:

    猜你喜欢
    • 2012-11-10
    • 1970-01-01
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    相关资源
    最近更新 更多