总结iOS App开发中控制屏幕旋转的几种方式

来源:互联网 发布:android网络框架 编辑:程序博客网 时间:2024/06/03 20:50

http://blog.csdn.net/li_shuang_ls/article/details/51792578

这篇文章主要介绍了iOS app开发中控制屏幕旋转的方法总结,分为自动旋转和手动旋转以及强制旋转三种情况,代码为Objective-C语言,需要的朋友可以参考下。


在iOS6之前的版本中,通常使用 shouldAutorotateToInterfaceOrientation 来单独控制某个UIViewController的方向,需要哪个viewController支持旋转,只需要重写shouldAutorotateToInterfaceOrientation方法。
但是iOS 6里屏幕旋转改变了很多,之前的 shouldAutorotateToInterfaceOrientation 被列为 DEPRECATED 方法,查看UIViewController.h文件也可以看到:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">// Applications should use supportedInterfaceOrientations and/or shouldAutorotate..    
  2.  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation NS_DEPRECATED_IOS(2_06_0);  </span>  


程序将使用如下2个方法来代替:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">- (BOOL)shouldAutorotate;    
  2. - (NSUInteger)supportedInterfaceOrientations;  </span>  

除了重写这个2个方法,IOS6之后要旋转还有一些需要注意的地方,下面会细述。另外还有一个硬性条件,需要在Info.plist文件里面添加程序支持的所有方向,可以通过以下2种方式添加

1.

201622991714779.png (493×56)

2.

201622991742247.png (492×242)

另外要兼容IOS6之前的系统,要保留原来的 shouldAutorotateToInterfaceOrientation 方法,还有那些 willRotateToInterfaceOrientation 等方法。


自动旋转设置:
控制某个viewController旋转并不是像IOS5或者IOS4一样在这个viewController里面重写上面那2个方法,而是需要在这个viewController的rootViewController(根视图控制器)里面重写,怎么解释呢?就是最前面的那个viewController,直接跟self.window接触的那个controller,比如以下代码:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">UIViewController *viewCtrl = [[UIViewController alloc] init];    
  2.  UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:viewCtrl];    
  3.  if ([window respondsToSelector:@selector(setRootViewController:)]) {    
  4.      self.window.rootViewController = navCtrl;    
  5.  } else {    
  6.      [self.window addSubview:navCtrl.view];    
  7.  }  </span>  

如果需要设置viewCtrl的旋转,那么不能在UIViewController里面重写shouldAutorotate和supportedInterfaceOrientations方法,而是需要在navCtrl里面设置,又因为UINavigationController是系统控件,所以这里需要新建一个UINavigationController的子navigationController的子类,然后在里面实现shouldAutorotate和supportedInterfaceOrientations方法,比如:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">-(NSUInteger)supportedInterfaceOrientations{    
  2.      return UIInterfaceOrientationMaskAllButUpsideDown;    
  3.  }    
  4.      
  5.  - (BOOL)shouldAutorotate{    
  6.      return YES;    
  7.  } </span>  

eg1:如果上面的例子是self.window.rootViewController = viewCtrl,而不是navCtrl,那么上面的那2个控制旋转的方法就应该写在UIViewController里面!

eg2:如果viewCtrl又pushViewController到viewCtrl2,需要设置viewCtrl2的旋转,怎么办呢? 还是在navCtrl里面控制,因为viewCtrl和viewCtrl2的rootViewController都是navCtrl,一般的写法都是

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">UIViewController *viewCtrl2 = [[UIVewController alloc] init];    
  2. [self.navigationController.navigationController pushViewController:viewCtrl2 animated:YES]; </span>  


所以要控制一个UINavigationController push到的所有viewController的旋转,那么就得在navCtrl里面区分是哪个viewController,以便对他们一一控制!同样如果rootViewController是UITabbarController,那么需要在子类化的UITabbarController里面重写那2个方法,然后分别控制!

但是有时候我初始化UINavigationController的时候,并不知道所有我所有需要push到的viewController,那么这里有一个通用的方法,就是让viewController自己来控制自己,首先在navCtrl里面的实现方法改为以下方式:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">- (BOOL)shouldAutorotate      
  2.  {      
  3.      return self.topViewController.shouldAutorotate;      
  4.  }      
  5.        
  6.  - (NSUInteger)supportedInterfaceOrientations      
  7.  {      
  8.      return self.topViewController.supportedInterfaceOrientations;      
  9.  }  </span>  

全部调用self.topViewController,就是返回当前呈现出来的viewController里面的设置,然后在viewCtrl、viewCtrl2等等这些viewController里面重写shouldAutorotate和supportedInterfaceOrientations,以方便设置每个viewController的旋转

eg3:如果viewCtrl 是 presentModalViewController 到 viewCtrl3,那么viewCtrl3的旋转设置就不在navCtrl里面了!如果presentModalViewController的viewController是navController、tabbarController包装过的viewCtrl3,那么就应在新包装的navController、tabbarController里面设置,如果是直接presentModalViewController到viewCtrl3,那么就在viewCtrl3里面设置。



手动旋转
手动旋转也有2种方式,一种是直接设置 UIDevice 的 orientation,但是这种方式不推荐,上传appStore有被拒的风险:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {    
  2.      [[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:(id)UIInterfaceOrientationPortrait];    
  3.  }</span>  

第二种是假旋转,并没有改变 UIDevice 的 orientation,而是改变某个view的 transform,利用 CGAffineTransformMakeRotation 来达到目的,比如:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">self.view.transform = CGAffineTransformMakeRotation(M_PI/2)  </span>  

下面讲解采用第二种方式的各版本手动旋转:
思想是首先设置 statusBarOrientation,然后再改变某个view的方向跟 statusBarOrientation 一致!

那既然是旋转,最少也得有2个方向,那么还是少不了上面说的那个硬性条件,先在plist里面设置好所有可能需要旋转的方向。既然是手动旋转,那么就要关闭自动旋转:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">- (BOOL)shouldAutorotate{    
  2.          return NO;    
  3.  }</span>  

手动触发某个按钮,调用方法,这个方法的实现如下:

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];    
  2.  self.view.transform = CGAffineTransformMakeRotation(M_PI/2);    
  3.  self.view.bounds = CGRectMake(00, kScreenHeight, 320); </span>  

注意:
1. 只需要改变self.view.transform,那么self.view的所有subview都会跟着自动变;其次因为方向变了,所以self.view的大小需要重新设置,不要使用self.view.frame,而是用bounds。
2. 如果shouldAutorotate 返回YES的话,下面设置setStatusBarOrientation 是不管用的!setStatusBarOrientation只有在shouldAutorotate 返回NO的情况下才管用!


强制旋转屏幕
最近接手了一个项目,正常情况下使用查看图片是没问题的。

用到了 MWPhotoBrowser 这个第三方图片浏览库。
不过发现了一个问题,就是设备横屏modal这MWPhotoBrowser的时候,发生了图片位置错乱。

实在没办法,所以想到了一个馊主意。

就是modal的时候使用代码把设备强制旋转回去。

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;">//UIDevice+WJ.h  
  2.  @interface UIDevice (WJ)  
  3.  /** 
  4.   *  强制旋转设备 
  5.  *  @param  旋转方向 
  6.  */  
  7.  + (void)setOrientation:(UIInterfaceOrientation)orientation;  
  8.  @end  
  9.  //UIDevice+WJ.m  
  10.  #import "UIDevice+WJ.h"  
  11.  @implementation UIDevice (WJ)  
  12.  //调用私有方法实现  
  13. + (void)setOrientation:(UIInterfaceOrientation)orientation {  
  14.      SEL selector = NSSelectorFromString(@"setOrientation:");  
  15.      NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self instanceMethodSignatureForSelector:selector]];  
  16.      [invocation setSelector:selector];  
  17.      [invocation setTarget:[self currentDevice]];  
  18.      int val = orientation;  
  19.      [invocation setArgument:&val atIndex:2];  
  20.      [invocation invoke];  
  21.  }  
  22.  @end</span>  


0 0