是否有书面的方式来设置iPhone的方向?

我有一个应用程序,我想支持设备旋转在某些意见,但其他没有特别有意义的风景模式,所以当我交换意见,我想强制旋转设置为肖像。

在UIDevice上有一个未公开的属性设置器,但是很明显会产生一个编译器警告,并且可能随着将来版本的SDK的消失而消失。

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 

有没有任何文件化的方法来强制这个方向?

更新:我想我会提供一个例子,因为我没有找到shouldAutorotateToInterfaceOrientation,因为我已经实现了。

我希望我的应用程序支持在视图1中的横向和纵向,但在视图2中只有纵向。我已经为所有视图实现了shouldAutorotateToInterfaceOrientation,但是如果用户在视图1中处于横向模式,然后切换到视图2,我想强制电话旋转回肖像。

这对于后来的iPhone 3.1.2 SDK不再是一个问题。 现在看来,要遵守被推回到堆栈上的视图的请求方向。 这可能意味着您需要检测较旧的iPhone操作系统版本,并且只在最新版本之前应用setOrientation。

目前尚不清楚苹果的静态分析是否会理解你正在解决旧的SDK限制。 我个人已经被苹果告知要删除我的下一个更新的方法调用,所以我不确定是否有旧设备的黑客将通过审批过程。

这很长时间以后,但万一有谁不使用导航控制器和/或不希望使用未记录的方法:

 UIViewController *c = [[UIViewController alloc]init]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO]; [c release]; 

呈现和解散香草视图控制器就足够了。

显然,你仍然需要确认或否定方向,你的覆盖shouldAutorotateToInterfaceOrientation。 但这会导致shouldAutorotate …被系统再次调用。

如果你想迫使它从肖像旋转到风景这里是代码。 请注意,您需要调整视图的中心。 我注意到我没有把这个观点放在正确的地方。 否则,它完美的工作。 谢谢你的提示。

 if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation)){ [UIView beginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:0.5f]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); self.view.center = CGPointMake(160.0f, 240.0f); [UIView commitAnimations]; } 

从我可以告诉, setOrientation:方法不起作用(或者可能不再工作)。 以下是我正在做的事情:

首先,把这个定义放在你的文件的顶部,正好在你的#imports下:

 #define degreesToRadian(x) (M_PI * (x) / 180.0) 

然后,在viewWillAppear:方法中

 [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO]; if (self.interfaceOrientation == UIInterfaceOrientationPortrait) { self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0, 0.0, 480, 320); } 

如果你想要动画,那么你可以把整个东西包装在一个动画块中,就像这样:

 [UIView beginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:1.25]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO]; if (self.interfaceOrientation == UIInterfaceOrientationPortrait) { self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0, 0.0, 480, 320); } [UIView commitAnimations]; 

然后,在您的肖像模式控制器中,您可以进行相反的检查,看它当前是否在横向,如果是,则将其旋转回肖像。

我遇到了一个问题,我在屏幕上有UIViewController ,在UINavigationController横向。 当下一个视图控制器被按下时,我需要设备返回到纵向。

我注意到的是,当一个新的视图控制器被压入堆栈时,不会调用shouldAutorotateToInterfaceOrientation:方法,但是当视图控制器从堆栈弹出时它会被调用

利用这一点,我在我的一个应用程序中使用这段代码:

 - (void)selectHostingAtIndex:(int)hostingIndex { self.transitioning = YES; UIViewController *garbageController = [[[UIViewController alloc] init] autorelease]; [self.navigationController pushViewController:garbageController animated:NO]; [self.navigationController popViewControllerAnimated:NO]; BBHostingController *hostingController = [[BBHostingController alloc] init]; hostingController.hosting = [self.hostings objectAtIndex:hostingIndex]; [self.navigationController pushViewController:hostingController animated:YES]; [hostingController release]; self.transitioning = NO; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { if (self.transitioning) return (toInterfaceOrientation == UIInterfaceOrientationPortrait); else return YES; } 

基本上,通过创建一个空视图控制器,将其推入堆栈,并立即弹出,可以使界面恢复到纵向位置。 一旦控制器弹出,我只需按下我想要推入的控制器。 从外观上看,它看起来不错 – 用户从来不会看到空的,任意的视图控制器。

有一个简单的方法来强制iPhone到必要的方向 – 使用kdbdallasJosh已经提供的两个答案:

 //will rotate status bar [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; //will re-rotate view according to statusbar UIViewController *c = [[UIViewController alloc]init]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO]; [c release]; 

奇迹般有效 :)

编辑:

对于iOS 6我需要添加这个功能:(工作在模态viewcontroller)

 - (NSUInteger)supportedInterfaceOrientations { return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight); } 

我一直在挖掘挖掘寻找一个很好的解决方案。 发现这个博客文章,做的伎俩:从关键的UIWindow删除最外层的视图,并再次添加它,系统然后将重新查询您的viewcontrollers shouldAutorotateToInterfaceOrientation:方法,强制执行正确的方向来应用。 看到它: iphone迫使uiview重新定位

乔希的回答对我很好。

不过,我更愿意发布“定位确实发生了变化,请更新UI”通知。 当视图控制器接收到此通知时,它将调用shouldAutorotateToInterfaceOrientation:允许您通过为所需的方向返回YES来设置任何方向。

 [[NSNotificationCenter defaultCenter] postNotificationName:UIDeviceOrientationDidChangeNotification object:nil]; 

唯一的问题是,这迫使没有动画的重新定位。 您需要在beginAnimations:commitAnimations之间包装这一行以实现平滑过渡。

希望有所帮助。

FWIW,这里是我手动设置方向的实现(进入你的应用的根视图控制器,natch):

 -(void)rotateInterfaceToOrientation:(UIDeviceOrientation)orientation{ CGRect bounds = [[ UIScreen mainScreen ] bounds ]; CGAffineTransform t; CGFloat r = 0; switch ( orientation ) { case UIDeviceOrientationLandscapeRight: r = -(M_PI / 2); break; case UIDeviceOrientationLandscapeLeft: r = M_PI / 2; break; } if( r != 0 ){ CGSize sz = bounds.size; bounds.size.width = sz.height; bounds.size.height = sz.width; } t = CGAffineTransformMakeRotation( r ); UIApplication *application = [ UIApplication sharedApplication ]; [ UIView beginAnimations:@"InterfaceOrientation" context: nil ]; [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ]; self.view.transform = t; self.view.bounds = bounds; [ UIView commitAnimations ]; [ application setStatusBarOrientation: orientation animated: YES ]; } 

再加上下面的UINavigationControllerDelegate方法(假设你使用的是UINavigationController ):

 -(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{ // rotate interface, if we need to UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ]; BOOL bViewControllerDoesSupportCurrentOrientation = [ viewController shouldAutorotateToInterfaceOrientation: orientation ]; if( !bViewControllerDoesSupportCurrentOrientation ){ [ self rotateInterfaceToOrientation: UIDeviceOrientationPortrait ]; } } 

这需要根据传入的UIViewController是否支持当前的设备方向来旋转根视图。 最后,您需要将rotateInterfaceToOrientation到实际的设备方向更改,以便模拟标准的iOS功能。 将此事件处理程序添加到同一个根视图控制器:

 -(void)onUIDeviceOrientationDidChangeNotification:(NSNotification*)notification{ UIViewController *tvc = self.rootNavigationController.topViewController; UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ]; // only switch if we need to (seem to get multiple notifications on device) if( orientation != [[ UIApplication sharedApplication ] statusBarOrientation ] ){ if( [ tvc shouldAutorotateToInterfaceOrientation: orientation ] ){ [ self rotateInterfaceToOrientation: orientation ]; } } } 

最后,在initloadview注册UIDeviceOrientationDidChangeNotification通知, loadview所示:

 [[ NSNotificationCenter defaultCenter ] addObserver: self selector: @selector(onUIDeviceOrientationDidChangeNotification:) name: UIDeviceOrientationDidChangeNotification object: nil ]; [[ UIDevice currentDevice ] beginGeneratingDeviceOrientationNotifications ]; 

这对我有用(谢谢亨利库克):

我的目标只是处理风景方向的变化。

init方法:

 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

 - (void)orientationChanged:(NSNotification *)notification { //[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; UIDeviceOrientation orientation = [UIDevice currentDevice].orientation; CGRect bounds = [[ UIScreen mainScreen ] bounds ]; CGAffineTransform t; CGFloat r = 0; switch ( orientation ) { case UIDeviceOrientationLandscapeRight: r = 0; NSLog(@"Right"); break; case UIDeviceOrientationLandscapeLeft: r = M_PI; NSLog(@"Left"); break; default:return; } t = CGAffineTransformMakeRotation( r ); UIApplication *application = [ UIApplication sharedApplication ]; [ UIView beginAnimations:@"InterfaceOrientation" context: nil ]; [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ]; self.view.transform = t; self.view.bounds = bounds; [ UIView commitAnimations ]; [ application setStatusBarOrientation: orientation animated: YES ]; } 

我有一个应用程序,我想支持设备旋转在某些意见,但其他没有特别有意义的风景模式,所以当我交换意见,我想强制旋转设置为肖像。

我意识到,在这个线程上面的原始帖子现在是非常老,但我有一个类似的问题 – 即。 在我的应用程序中的所有屏幕只有肖像,除了一个屏幕,可以在用户的​​风景和肖像之间旋转。

这足够简单,但像其他职位,我希望应用程序自动返回到肖像,无论当前设备的方向,当返回到前一个屏幕。

我实现的解决方案是在横向模式下隐藏导航栏,这意味着用户只能在纵向时返回到以前的屏幕。 因此,所有其他屏幕只能是肖像。

 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)pInterfaceOrientation { BOOL lHideNavBar = self.interfaceOrientation == UIInterfaceOrientationPortrait ? NO : YES; [self.navigationController setNavigationBarHidden:lHideNavBar animated:YES]; } 

这也对我的应用程序有额外的好处,因为在横向模式下有更多的可用屏幕空间。 这是有用的,因为有问题的屏幕用于显示PDF文件。

希望这可以帮助。

我最终很容易解决这个问题。 我尝试了上面的每一个建议,仍然是短暂的,所以这是我的解决方案:

在需要保持横向(左或右)的ViewController中,我倾听方向更改:

  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

然后在didRotate中:

 - (void) didRotate:(NSNotification *)notification { if (orientationa == UIDeviceOrientationPortrait) { if (hasRotated == NO) { NSLog(@"Rotating to portait"); hasRotated = YES; [UIView beginAnimations: @"" context:nil]; [UIView setAnimationDuration: 0]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-90)); self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); self.view.frame = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); [UIView commitAnimations]; } } else if (UIDeviceOrientationIsLandscape( orientationa)) { if (hasRotated) { NSLog(@"Rotating to lands"); hasRotated = NO; [UIView beginAnimations: @"" context:nil]; [UIView setAnimationDuration: 0]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0)); self.view.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f); self.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f); [UIView commitAnimations]; } } 

请记住所有使用自动调整大小的超级视图/子视图,因为view.bounds / frame被显式重置…

唯一需要注意的是保持视图横向的方法,就是必须发生的方向之间固有的动画切换,最好看起来没有变化。

iOS 6解决方案:

 [[[self window] rootViewController] presentViewController:[[UIViewController alloc] init] animated:NO completion:^{ [[[self window] rootViewController] dismissViewControllerAnimated:NO completion:nil]; }]; 

确切的代码取决于每个应用程序,也是你把它放在哪里(我用它在我的AppDelegate)。 用你所用的东西替换[[self window] rootViewController] 。 我正在使用UITabBarController

我找到了一个解决方案,用法语写了一些东西(但代码是英文的)。 这里

方法是将控制器添加到窗口视图中(控制器必须拥有shouldRotate ….函数的良好实现)。

如果你正在使用UIViewControllers,有这种方法:

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

包含您不想旋转的视图的视图控制器返回NO

更多信息在这里

我不认为这是可能的在运行时间,虽然你当然可以申请一个90度的转换到你的用户界面。

这是我用的。 (你得到一些编译警告,但它在模拟器和iPhone中都可以)

 [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];