防止导航控制器中的一些视图控制器旋转
我有一个导航控制器,它一次显示两个视图控制器。它们是分层的,并且最前面的控制器可以被拖拽到下面显示控制器。 我的应用程序代理已配置,因此应用程序只会在后面的视图显示时允许界面方向,如下所示。防止导航控制器中的一些视图控制器旋转
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (self.revealNavigationController.isViewRevealed)
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
当然,这会导致前后视图控制器在设备旋转时旋转,但我只对旋转后视图控制器感兴趣。 有没有什么办法可以在最前面的视图控制器中完全禁用旋转?
由axiixc建议的解决方案通常更好,这取决于你的问题,你应该look at his answer。但是,这并没有解决我的问题。我有一个UINavigationController
,其中我将视图控制器的视图作为索引0的子视图插入。这样,视图就位于后面。然后我做了可拖动的拖拽,这样当它拖拽时,它会在后面显示视图。然后,最前面的视图将随导航栏一起移动。 正如axiixc所建议的那样,我没有设法让它与视图控制器遏制API引入iOS 5一起工作。
取而代之,我从导航控制器中删除了视图,并在启动应用程序时将其直接添加到UIWindow
,我自己处理了此视图的旋转并禁用了所有其他视图的旋转(即,我禁用了该视图导航控制器)。
这是我如何添加视图-application:didFinishLaunchingWithOptions:
self.revealViewController = [[RevealViewController alloc] init];
[self.window insertSubview:self.revealViewController.view atIndex:0];
后,立刻,我注册了UIDeviceOrientationDidChangeNotification
。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
我didRotate:
看起来是这样的:
- (void)didRotate:(NSNotification *)notification
{
// Only rotate if the view is revealed
if (self.revealNavigationController.isViewRevealed)
{
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
[self updateForDeviceOrientation:orientation animated:YES];
}
}
我打电话-updateForDeviceOrientation:animated:
- (void)updateForDeviceOrientation:(UIDeviceOrientation)orientation animated:(BOOL)animated
{
CGFloat degrees = 0.0f;
switch (orientation)
{
case UIDeviceOrientationLandscapeLeft:
degrees = 90.0f;
break;
case UIDeviceOrientationLandscapeRight:
degrees = -90.0f;
break;
case UIDeviceOrientationPortrait:
degrees = 0.0f;
break;
default:
break;
}
CGFloat duration = (animated) ? [UIApplication sharedApplication].statusBarOrientationAnimationDuration : 0.0f;
__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:duration animations:^{
// Rotate view
weakSelf.revealViewController.view.transform = CGAffineTransformIdentity;
weakSelf.revealViewController.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));
// Resize view for rotation
CGFloat width, height;
if (UIDeviceOrientationIsLandscape(orientation))
{
width = MAX(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
height = MIN(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
}
else
{
width = MIN(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
height = MAX(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
}
CGSize newSize = CGSizeMake(width, height);
CGRect viewBounds = weakSelf.revealViewController.view.bounds;
viewBounds.size = newSize;
weakSelf.revealViewController.view.bounds = viewBounds;
CGRect viewFrame = weakSelf.revealViewController.view.frame;
viewFrame.size = newSize;
weakSelf.revealViewController.view.bounds = viewFrame;
}];
}
是的,看看UIViewController中的-supportedInterfaceOrientations方法。您返回一个UIInterfaceOrientationMask位掩码,指定您希望UIViewController子类支持的方向。
我刚刚尝试在'-supportedInterfaceOrientations'中的'-sharedAutorotate'和'UIInterfaceOrientationMaskPortrait'中返回'NO',并将其放在我最前面的一个控制器中。虽然'-supportedInterfaceOrientations'在视图呈现但不旋转时被调用,它似乎被忽略。视图控制器仍然尝试旋转视图并在横向方向上满足自动布局约束。 – simonbs 2013-04-30 20:18:54
'-shaouldAutorotate'不被调用,但。 – simonbs 2013-04-30 20:22:06
您需要使用在iOS5中添加的视图控制器包含API。基本上,当你不再需要它参与旋转事件时,你需要做的是删除你的一个视图控制器,并在它再次准备好时再添加它。样品将是...
@implementation AXRotationDemoViewController
- (id)init
{
if ((self = [super init]))
{
self.oneViewController = [[AXLoggingViewController alloc] init];
self.oneViewController.interfaceOrientations = UIInterfaceOrientationMaskPortrait;
self.twoViewController = [[AXLoggingViewController alloc] init];
self.twoViewController.interfaceOrientations = UIInterfaceOrientationMaskAllButUpsideDown;
}
return self;
}
- (void)viewDidLoad
{
[self.oneViewController willMoveToParentViewController:self];
[self addChildViewController:self.oneViewController];
[self.view addSubview:self.oneViewController.view];
[self.oneViewController didMoveToParentViewController:self];
[self.twoViewController willMoveToParentViewController:self];
[self addChildViewController:self.twoViewController];
[self.view addSubview:self.twoViewController.view];
[self.twoViewController didMoveToParentViewController:self];
self.oneViewController.view.backgroundColor = [UIColor redColor];
self.twoViewController.view.backgroundColor = [UIColor greenColor];
UIButton * showBackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[showBackButton setTitle:@"Toggle Back/Front" forState:UIControlStateNormal];
[showBackButton addTarget:self action:@selector(_toggle:) forControlEvents:UIControlEventTouchUpInside];
[showBackButton sizeToFit];
showBackButton.center = self.view.center;
[self.view addSubview:showBackButton];
}
- (void)_toggle:(id)sender
{
if ([self.childViewControllers containsObject:self.oneViewController])
{
[self.oneViewController.view removeFromSuperview];
[self.oneViewController removeFromParentViewController];
}
else
{
[self.oneViewController willMoveToParentViewController:self];
[self addChildViewController:self.oneViewController];
[self.view addSubview:self.oneViewController.view];
[self.oneViewController didMoveToParentViewController:self];
UIWindow * window = self.view.window;
UIViewController * hack = window.rootViewController;
window.rootViewController = nil;
window.rootViewController = hack;
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect halfScreenFrame = self.view.bounds;
halfScreenFrame.size.height /= 2;
self.oneViewController.view.frame = halfScreenFrame;
self.twoViewController.view.frame = CGRectOffset(halfScreenFrame, 0, halfScreenFrame.size.height);
}
- (NSUInteger)supportedInterfaceOrientations
{
if ([self.childViewControllers containsObject:self.oneViewController])
return self.oneViewController.supportedInterfaceOrientations;
return self.twoViewController.supportedInterfaceOrientations;
}
@end
然而,你可能会注意到,有一个真正告诉iOS的没有正式的方式,你已经改变的supportedInterfaceOrientations
价值,所以最好的办法是A)使用黑客像我上面的例子强制iOS重做一切,或者b)不要让用户关闭后视图,直到设备再次处于肖像状态。
这里是sample我放在一起,如果这不能解释得很好。
这将是理想的方法,但我没有设法在这种情况下得到这个工作。有关我的解决方案,请参阅http://*.com/a/16354167/486845。 – simonbs 2013-05-03 08:02:32
是(这是由在计算器上另一个答案,我现在无法再次找到,遗憾的启发)你的问题是,用户可以揭示后视图,侧向旋转,然后隐藏它,主视图仍然横向,或者主视图即使在屏幕外时也会旋转? – axiixc 2013-04-30 20:26:14
@axiixc问题在于主视图在屏幕外旋转。视图控制器并非真正支持方向更改,因此如果您显示后视图,旋转到横屏,旋转回肖像并再次隐藏后视图以显示主视图,主视图会混乱。理想情况下,我希望主要视图不可能旋转。这将解决你提到的两个问题。因此,如果用户显示后视图,侧向旋转并隐藏它,主视图仍然是肖像。 – simonbs 2013-04-30 20:30:29