IOS屏幕3.5寸和4寸屏幕适配 之 适配ios6转屏

来源:互联网 发布:win7摄像头软件amcap 编辑:程序博客网 时间:2024/04/29 20:02

今天Boss跟我说,要我准备去适配ios6,于是我去鸟哥的博客看了下,然后有请教了别人,但是没达到效果,一直不知道问题在哪,后来看文档,google才发现问题关键所在。现在大致说下:

     

在ios6.0中shouldAutorotateToInterfaceOrientation:不再起作用了,ios使用shouldAutorotate和supportedInterfaceOrientations来控制旋转效果。
我试了几次,发现ios6.0真正起作用的旋转有三种:
1.在info.plist这里设置来控制,还可以在appDelegate的这个函数里面设置

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window,在这个里面设置了,那么info.plist里面设置的就会失效;

2.直接把视图加在window上,(如:[self.window addSubview:vc.view])这种方法可以脱离info.plist的控制,

shouldAutorotate和supportedInterfaceOrientations来控制方向;
3.使用rootViewController(如:self.window.rootViewController = rootVC) , 添加shouldAutorotate方法,但是受info.plist的限制。

相信大多数人都是使用的第三种,但是这个要特别注意:当window的rootViewController设置为UINavigationController的时候,你需要自定义UINavigationController,因为你需要在这里面,写shouldAutorotate和supportedInterfaceOrientations方法。如果你不这样做,那么如果你有的界面需要转屏的话,可能会有问题。
上面的这些方法都限制于顶层视图控制,这也是ios6与之前的ios版本不同的地方,如果要想在子视图中添加旋转效果,则需要在顶层视图中开启shouldAutorotate方法,在子视图控制器中就可以使用supportedInterfaceOrientations方法。
一些示例代码:
首先
[plain] view plaincopy
  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
  2. {  
  3.     self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];  
  4.     // Override point for customization after application launch.  
  5.     RootViewController  *vc   = [[RootViewController alloc] init];  
  6.     self.window.rootViewController = vc;  
  7.     [vc release];  
  8.     [self.window makeKeyAndVisible];  
  9.       
  10. //  直接添加视图来控制  
  11. //  RootViewController *vc = [[RootViewController alloc] init];      
  12. //  [self.window addSubview:vc.view];  
  13.     return YES;  
  14. }  
然后在顶层视图上开启旋转和控制
[plain] view plaincopy
  1. //在RootViewController中开启旋转  
  2. - (BOOL)shouldAutorotate  
  3. {  
  4.     return YES;  
  5. }  
  6.   
  7. -(NSUInteger)supportedInterfaceOrientations  
  8. {  
  9.     return UIInterfaceOrientationMaskLandscape;  
  10. }  
最后在子视图控制器中直接使用
[plain] view plaincopy
  1. //- (BOOL)shouldAutorotate  
  2. //{  
  3. //    return YES;  
  4. //}  
  5.   
  6. //在FirstViewController中直接使用  
  7. -(NSUInteger)supportedInterfaceOrientations  
  8. {  
  9.     return UIInterfaceOrientationMaskPortrait;  
  10. }  
总结:
    在ios4 and 5 , 都是由具体的ViewController来决定对应的view的orientation设置,但是在ios6,则是由top-most controller,即顶层视图控制器来决定view的orientation设置。

在iOS 4 and 5,都是由具体的view controller来决定对应的view的orientation设置。而在iOS 6,则是由top-most  controller来决定view的orientation设置。

就像我们刚才说的那个:如果你的app的window的rootViewController是UINavigationController的nav,那么在nav里的stack依次是:main view ->sub view ->sub sub view, 并且在main view里面可以进入下一个视图model view,是present进去的, 那么在ios4 and 5 ,如果你要这些view只支持横屏orientation,那么你只需要在main view, sub view ,sub sub view ,model view的控制器里面,添加这个函数即可:

[plain] view plaincopy
  1. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
  2. {  
  3.     return UIInterfaceOrientationIsLandscape(orientation);  
  4. }  

[cpp] view plaincopy
  1. <span style="font-size: 14px; color: rgb(51, 51, 51); font-family: Arial; line-height: 26px; white-space: pre-wrap; background-color: rgb(255, 255, 255);">但是对于ios6来说,由于是top-most controller来设置方向的,因此如果你单独的在main view ,sub view,sub sub view里面添加下面的代码是没有任何效果的,而应该是在navigationController里添加下列代码,这也是因为我先为什么说,需要你自定义navigationController的原因。而modal view 并不在navigaitonController的控制之下,所以你需要在model view里也添加下面的代码:</span>  

[plain] view plaincopy
  1. - (BOOL)shouldAutorotate    
  2. {    
  3.    return YES;    
  4. }    
  5. -(NSUInteger)supportedInterfaceOrientations{    
  6.     return UIInterfaceOrientationMaskLandscape;    
  7. }    

[cpp] view plaincopy
  1.   

注意:

*你需要自定义一个UINavigationController的子类,这样才可以添加上述代码。

* 和UINavigationController类似,tab controller里的各个view的orientation设置应该放在tab controller里

对于 ios6的top-most controller决定orientation设置,导致这样一个问题:在 top-most controller里的views无法拥有不相同的orientation设置。例如:在nav controller里,你有main view, sub view and sub sub view,前2个都只能是竖屏,而sub sub view是用来播放视频的,可以横竖屏。那么在ios 4 and 5里可以通过在main view and sub view的shouldAutorotateToInterfaceOrientation里设置只能竖屏,而在sub sub view的shouldAutorotateToInterfaceOrientation设置横竖屏即可。而在ios 6里则无法实现这种效果,因为在main view, sub view and sub sub view的orientation设置是无效的,只能够在nav controller里设置。那么你可能想着用下列代码在nav controller里控制哪个view竖屏,哪个view横屏

[plain] view plaincopy
  1. -(NSUInteger)supportedInterfaceOrientations{    
  2.     if([[self topViewController] isKindOfClass:[SubSubView class]])    
  3.         return UIInterfaceOrientationMaskAllButUpsideDown;    
  4.     else    
  5.         return UIInterfaceOrientationMaskPortrait;    
  6. }    

是的,这样可以使得在main view and sub view里无法横屏,而sub sub view横竖屏都行。但问题来了,如果在sub sub view时横屏,然后back to sub view,那么sub view是横屏显示的!

目前想到的解决方法只能是把sub sub view脱离nav controller,以modal view方式来显示。这样就可以在modal view里设置横竖屏,而在nav controller里设置只竖屏。

* 说了那么多,其实如果你的app的所有view的orientation的设置是统一的,那么你可以简单的在plist file里设置即可,不用添加上面的代码。而如果你添加了上面的代码,就会覆盖plist里orientation的设置。

* in iOS 6, 当view controller present时,不会call willRotateToInterfaceOrientation:duration:, willAnimateRotationToInterfaceOrientation:duration:, and didRotateFromInterfaceOrientation: methods,只有在发生rotate的时候才会call

以上资料的参考了别人的博文和自己在适配ios6转屏的一些心得
感谢

Tomson Xu