Ste*_*eld 24 iphone cocoa-touch rotation uinavigationcontroller
我有一个返回一个UIViewController YES
中shouldAutorotateToInterfaceOrientation:
为UIDeviceOrientationPortrait
和NO
其他一切.在堆栈顶部的那个视图中,我pushViewController:animated:
用来推动一个新的UIViewController
.新控制器返回YES
任何内容shouldAutorotateToInterfaceOrientation:
.
第一个视图拒绝旋转(如预期的那样).按下第二个视图后,用户可以旋转设备,UI将旋转(也如预期).如果第二个视图处于横向模式并且用户按下后退按钮(调用popViewControllerAnimated:
),则第一个视图将显示为旋转(意外!).
如果用户将设备旋转回纵向,则视图将旋转,然后像以前一样卡在纵向模式中.这可行,但对于用户来说,它们会旋转回来之前很难看.所以我正在寻找一种让这种观点保持纵向模式的方法.
到目前为止我找到的唯一解决方法是使用-[UIDevice setOrientation:]
,它会抛出一个警告(orientation
只读),但是因为实际定义了它.这是一个巨大的黑客,我想要一个真正的解决方案.为了寻找真正的解决方案,我将GDB附加到了Photos应用程序(MobileSlideshow.app)并发现它也使用了-[UIDevice setOrientation:]
.作为一个内部应用程序虽然我猜他们有不同的规则.
有没有正确的方法来实现预期的自转行为?
UIDevice setOrientation的合法替代方法如下:
UIWindow* window = UIApplication.sharedApplication.keyWindow;
UIView* view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];
Run Code Online (Sandbox Code Playgroud)
这会强制当前视图控制器评估其方向,调用shouldAutorotateToInterfaceOrientation并切换远离任何禁止的方向.
例如,以下代码将用于支持所有方向但其父级仅支持格局的视图控制器中:
- (void)popBack
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
- (IBAction)backPressed:(id)sender
{
portraitOrientationPermitted = NO;
// Force the framework to re-evaluate the interface orientation.
UIWindow* window = UIApplication.sharedApplication.keyWindow;
UIView* view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];
[self performSelector:@selector(popBack) withObject:nil afterDelay:0.8];
portraitOrientationPermitted = YES;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return portraitOrientationPermitted ||
UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
Run Code Online (Sandbox Code Playgroud)
这是一个老帖子,但因为它还没有解决.我想与其他可能头疼的人分享我的解决方案.
目标:UINavigationController和其堆栈中的大多数viewcontrollers固定在纵向,除了堆栈中的一个viewcontroller允许旋转到纵向和横向.
问题:直观地我通过检查topViewController是否是rotableViewController来设置一个选择性的shouldAutorotateToInterfaceOrientation.但是,在横向模式下从rotableViewController弹回后,导航控制器现在以横向模式显示,尽管不允许.
解决方案:杀手是禁止旋转,viewWillAppear
并在没有动画的情况下呈现和解除modalViewController.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) return YES;
return canRotate;
}
Run Code Online (Sandbox Code Playgroud)
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[viewController viewDidAppear:animated];
canRotate = ([navigationController.topViewController isKindOfClass:[MyRotatable class]]);
}
Run Code Online (Sandbox Code Playgroud)
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[viewController viewWillAppear:animated];
if (![navigationController.topViewController isKindOfClass:[MyRotatable class]]) {
canRotate = NO;
UIViewController * blanck = [[UIViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:blanck animated:NO];
[self dismissModalViewControllerAnimated:NO];
[blanck release];
}
}
Run Code Online (Sandbox Code Playgroud)
我正想告诉你,可能没有办法,但后来我有了一个想法。很难做到正确,但如果您使用两个单独的UINavigationController
s ,您也许可以使其工作:一个控制根视图并禁止旋转,另一个用于允许旋转的子视图。您将手动处理根控制器和子控制器之间的转换。
您必须修补子导航控制器才能拥有正确的后退按钮。当然,您必须自己按下后退按钮。您可能必须使用虚拟对象UINavigationBar
来执行从一个导航控制器到下一个导航控制器的动画,以便过渡看起来正确。您还必须为导航控制器之间的“推送”转换设置动画,这可能需要进行一些调整才能使其看起来正确。你必须:
UINavigationItem
并将其推送)UINavigationItem
为传入视图控制器创建一个副本并将其推送到虚拟导航栏上UINavigationBar
从视图中删除虚拟对象以及传出的导航控制器。所有这些都需要大量工作,但如果您非常聪明(并且非常顽强),您也许能够让它发挥作用。我很想看到结果!
也就是说,您最好只使用setOrientation:
App Store 审批流程并抓住机会;-)