简体   繁体   English

在设备旋转期间如何“锁定”视图的方向

[英]How to “lock” a view's orientation during device rotation

Let's say I have a view controller, call it ViewControllerPortrait, which is designed to display in portrait mode only. 假设我有一个视图控制器,称为ViewControllerPortrait,它仅设计为以纵向模式显示。 Eg: 例如:

ViewControllerPortrait

When the user rotates the device to landscape, I don't want ViewControllerPortrait to ever re-orient itself to landscape, but I do want to present a new full-screen view. 当用户将设备旋转为横向时,我不希望ViewControllerPortrait再次将自身重新定向为横向,但我确实希望呈现一个新的全屏视图。 Let's call the full-screen view controller ViewControllerLandscapeFull. 我们将其称为全屏视图控制器ViewControllerLandscapeFull。 Eg: 例如:

在此处输入图片说明

What I don't ever want to see is this: 我永远不想看到的是:

不要这样

The way I tried to do this is to have the window's rootViewController present ViewControllerLandscapeFull in full screen when it gets a willRotateToInterfaceOrientation:duration: 我尝试执行此操作的方法是让窗口的rootViewController在获取willRotateToInterfaceOrientation:duration:时全屏显示ViewControllerLandscapeFull willRotateToInterfaceOrientation:duration:

[[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];

And then in ViewControllerLandscapeFull I have: 然后在ViewControllerLandscapeFull中,我有:

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

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

This works fairly well. 这工作得很好。 Since ViewControllerLandscapeFull "prefers" landscape and has a UIModalPresentationFullScreen modalPresentationStyle , it only ever shows in landscape. 由于ViewControllerLandscapeFull“更喜欢”风景并且具有UIModalPresentationFullScreen modalPresentationStyle ,因此它仅在风景中显示。 By returning landscape | portrait 返回landscape | portrait landscape | portrait for supportedInterfaceOrientations, device rotations back to portrait are allowed which happens when ViewControllerLandscapeFull gets willRotateToInterfaceOrientation:duration: and eventually dismissViewControllerAnimated:NO is called on it. landscape | portrait用于supportedInterfaceOrientations,设备旋转回纵向被允许时ViewControllerLandscapeFull得到这恰好willRotateToInterfaceOrientation:duration:最终dismissViewControllerAnimated:NO叫就可以了。

The only problem I have is that during the rotation back to portrait, you can momentarily see ViewControllerPortrait in landscape orientation, and that's what I'm trying to avoid. 我唯一的问题是,在旋转回纵向时,您可以暂时以横向看到ViewControllerPortrait,这就是我要避免的事情。

ViewControllerPortrait does implement: ViewControllerPortrait确实实现了:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

And I've verified that UIKit is calling it but it apparently has no effect. 而且我已经证实UIKit正在调用它,但是它显然没有作用。 (The docs say that supportedInterfaceOrientations is only called on root view controllers and view controllers presented full screen, so I'm actually surprised UIKit calls it at all.) (文档说, supportedInterfaceOrientations仅在根视图控制器上调用,并且视图控制器全屏显示,因此,我真的很惊讶UIKit完全调用它。)

FWIW, I'm working with the iOS 8 beta 5 SDK and building for 7/8. FWIW,我正在使用iOS 8 beta 5 SDK,并为7/8构建。

Muchas gracias. Muchas gracias。

I'm just beginning programming with iPhones, but maybe this will work... 我刚刚开始使用iPhone进行编程,但这也许行得通...

Click on your project file > deployment info. 单击项目文件>部署信息。 Then unclick everything except portrait. 然后取消单击除肖像以外的所有内容。 This way rotating the device won't reorientate itself. 这样,旋转设备不会重新定位自身。

However, you can still test whether the device rotates or not with this: 但是,您仍然可以使用以下方法测试设备是否旋转:

- (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;
}
houldAutorotate, supportedInterfaceOrientations, preferredInterfaceOrientationForPresentation

The above methods don't get called of a viewcontroller if they are inside any tabbarcontroller of navigationcontroller. 如果上述方法位于Navigationcontroller的任何tabbarcontroller中,则不会调用viewcontroller。 If these methods are declared inside tabbarcontroller or navigation controller then they will get called. 如果在tabbarcontroller或导航控制器中声明了这些方法,则将调用它们。 In my case the viewcontrollers was inside navigationcontroller and the navigation controllers are inside a tabbarcontroller. 在我的情况下,视图控制器位于navigationcontroller内,而导航控制器位于tabbarcontroller内。

For solving this I make a class FixedOrientationTab , it is a subclass of UITabBarController , and a navigation class OrientationEnabledNavigation , it is a subclass of UINavigationController . 为了解决这个问题,我创建了FixedOrientationTab类,它是UITabBarController的子类,而导航类OrientationEnabledNavigationUINavigationController的子类。 Then I implemented shouldAutorotate , supportedInterfaceOrientations , preferredInterfaceOrientationForPresentation methods inside FixedOrientationTab and OrientationEnabledNavigation . 然后,我实现shouldAutorotatesupportedInterfaceOrientationspreferredInterfaceOrientationForPresentation方法里面FixedOrientationTabOrientationEnabledNavigation

OrientationEnabledNavigation.h OrientationEnabledNavigation.h

#import <UIKit/UIKit.h>

@interface OrientationEnabledNavigation : UINavigationController

@end

OrientationEnabledNavigation.m 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 FixedOrientationTab.h

#import <UIKit/UIKit.h>

@interface FixedOrientationTab : UITabBarController

@end

FixedOrientationTab.m 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

Then if you want to use navigation controller in your project then use OrientationEnabledNavigation and for tabbar FixedOrientationTab . 然后,如果要在项目中使用导航控制器,请使用OrientationEnabledNavigation并将其用于FixedOrientationTab After that if you implement shouldAutorotate , supportedInterfaceOrientations , preferredInterfaceOrientationForPresentation these method inside your viewcontroller then they will get called. 之后,如果您在viewcontroller中实现了shouldAutorotatesupportedInterfaceOrientationspreferredInterfaceOrientationForPresentation这些方法,则将调用它们。

Hope this helps.. :) 希望这可以帮助.. :)

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

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