现在的位置: 首页 > 综合 > 正文

IOS6屏幕旋转问题总结 .          ios6 设备旋转以及获取设备方向

2018年02月14日 ⁄ 综合 ⁄ 共 10648字 ⁄ 字号 评论关闭

概述:

在iOS6之前的版本中,通常使用 shouldAutorotateToInterfaceOrientation 来单独控制某个UIViewController的方向,需要哪个viewController支持旋转,只需要重写shouldAutorotateToInterfaceOrientation方法。

但是iOS 6里屏幕旋转改变了很多,之前的 shouldAutorotateToInterfaceOrientation 被列为 DEPRECATED 方法,查看UIViewController.h文件也可以看到:

  1. // Applications should use supportedInterfaceOrientations and/or shouldAutorotate..  
  2. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation NS_DEPRECATED_IOS(2_0, 6_0);  

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

  1. - (BOOL)shouldAutorotate;  
  2. - (NSUInteger)supportedInterfaceOrientations;  

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

1.



2.



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

IOS6自动旋转设置:

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

  1. 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. }  

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

  1. -(NSUInteger)supportedInterfaceOrientations{  
  2.     return UIInterfaceOrientationMaskAllButUpsideDown;  
  3. }  
  4.   
  5. - (BOOL)shouldAutorotate{  
  6.     return YES;  
  7. }  
eg1:如果上面的例子是self.window.rootViewController = viewCtrl,而不是navCtrl,那么上面的那2个控制旋转的方法就应该写在UIViewController里面!

eg2:如果viewCtrl又pushViewController到viewCtrl2,需要设置viewCtrl2的旋转,怎么办呢?
还是在navCtrl里面控制,因为viewCtrl和viewCtrl2的rootViewController都是navCtrl,一般的写法都是
  1. UIViewController *viewCtrl2 = [[UIVewController alloc] init];  
  2. [self.navigationController.navigationController pushViewController:viewCtrl2 animated:YES];  
所以要控制一个UINavigationController push到的所有viewController的旋转,那么就得在navCtrl里面区分是哪个viewController,以便对他们一一控制!同样如果rootViewController是UITabbarController,那么需要在子类化的UITabbarController里面重写那2个方法,然后分别控制!

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

  1. - (BOOL)shouldAutorotate    
  2. {    
  3.     return self.topViewController.shouldAutorotate;    
  4. }    
  5.     
  6. - (NSUInteger)supportedInterfaceOrientations    
  7. {    
  8.     return self.topViewController.supportedInterfaceOrientations;    
  9. }  

全部调用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里面设置


IOS5、IOS4自动旋转设置

这个简单很多,没有上面的硬性条件,只需要在需要旋转的viewController里面重写 shouldAutorotateToInterfaceOrientation
方法就行

手动旋转

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

  1. if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {  
  2.     [[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:(id)UIInterfaceOrientationPortrait];  
  3. }  

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

  1. self.view.transform = CGAffineTransformMakeRotation(M_PI/2)  


下面讲解采用第二种方式的各版本手动旋转:

思想是首先设置 statusBarOrientation,然后再改变某个view的方向跟 statusBarOrientation 一致!


IOS6手动旋转:

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

  1. - (BOOL)shouldAutorotate{  
  2.         return NO;  
  3. }  

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

  1. [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];  
  2. self.view.transform = CGAffineTransformMakeRotation(M_PI/2);  
  3. self.view.bounds = CGRectMake(0, 0, kScreenHeight, 320);  

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

IOS5、IOS4手动旋转:

1.在需要手动旋转的viewController里的 shouldAutorotateToInterfaceOrientation 方法设置 interfaceOrientation == [UIApplicationsharedApplication].statusBarOrientation

  1. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{  
  2.     return (interfaceOrientation == [UIApplication sharedApplication].statusBarOrientation);  
  3. }  

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

  1. [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];  
  2. self.view.transform = CGAffineTransformMakeRotation(M_PI/2);  
  3. self.view.bounds = CGRectMake(0, 0, kScreenHeight, 320);  

注意:只需要改变self.view.transform,那么self.view的所有subview都会跟着自动变;其次因为方向变了,所以self.view的大小需要重新设置,不要使用self.view.frame,而是用bounds。


经验分享:

1.IOS6里面,如果一个项目里面需要各种旋转支持,有自动,有手动,那么我们可以新建2个navController或者tabbarController的子类,一个是不旋转,一个旋转,那么所有需要旋转的UINavigationController都可以用这个子类来代替!包括我们可以定制短信呀、邮件呀的旋转!
2.supportedInterfaceOrientations 方法一般是写UIInterfaceOrientationMask方向,但是如果程序要兼容4.3以下的SDK(4.3以下的SDK必须是4.5以下的Xcode,不支持IOS6),那么在用4.5以下的Xcode编译的时候通不过!所以可以用statusBarOrientation代替或者直接写死数字!

  1. -(NSUInteger)supportedInterfaceOrientations{  
  2.     return [UIApplication sharedApplication].statusBarOrientation;  
  3. }  

3.一般都不建议在程序里面直接调用 UIDeviceOrientation 的方向,而是用 UIInterfaceOrientation,他们之间是不同的!

  1. UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,  
  2. UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft  

看到吗,左右是反的!Xcode图形化设置方向也是以 UIInterfaceOrientation 为准,就是home按键所在的方向

参考:

http://blog.csdn.net/totogogo/article/details/8002173

http://stackoverflow.com/questions/13200220/how-to-change-keyboard-orientation-in-ios6

http://blog.csdn.net/yiyaaixuexi/article/details/8035014


第二篇文章:讲解旋转过程中的各个方法调用

         ios6 设备旋转以及获取设备方向

1.在APPDelegate里,将
[self.window addSubview:self.viewController.view];  

改为判断当前设备系统  
     if ([[[UIDevice currentDevice] systemVersion] floatValue]>=4.0) {  
         //4.0以后支持  
         self.window.rootViewController = self.viewController;  
       }  
     else  
         [self.window addSubview:self.viewController.view];  

2.在viewController.m中重写方法

//ios6以后设备旋转  
    - (BOOL)shouldAutorotate  
    {  
        return YES;  
    }  
    - (NSUInteger)supportedInterfaceOrientations  
    {  
        NSLog(@"ios6");  
        return UIInterfaceOrientationMaskAll;  
    //    self.interfaceOrientation  
          
    }  
    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation  
    {  
        NSLog(@"设备旋转");  
    }  

要翻转的时候,首先响应的方法:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

return YES则支持翻转,NO则不支持。

紧接着

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

被调用。这个方法是发生在翻转开始之前。一般用来禁用某些控件或者停止某些正在进行的活动,比如停止视频播放。
再来是

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

这个方法发生在翻转的过程中,一般用来定制翻转后各个控件的位置、大小等。可以用另外两个方法来代替:willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:   和  willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:

最后调用的是

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

这个方法发生在整个翻转完成之后。一般用来重新启用某些控件或者继续翻转之前被暂停的活动,比如继续视频播放

3,在info。plist中增加相对应的方向即可

4.获取自身屏幕方法,不要使用[[UIDevice currentDevice] orientation](第一次使用的时候,总是返回0)
而是要使用self.interfaceOrientation或[[UIApplication sharedApplication] statusBarOrientation]

第三篇讲收到设备旋转的通知后调用设置坐标方法
横竖屏切换,视图乱了怎么办?

首先,我们必须了解一下下列4种状态,它们被用来描述设备旋转方向:

UIInterfaceOrientationLandscapeLeft

向左,即HOME键在右

UIInterfaceOrientationLandscapeRight

向右,即HOME键在左

UIInterfaceOrientationPortrait

正立,即HOME键在下

UIInterfaceOrientationPortraitUpsideDown

倒立,即HOME键在上

 

对于旋屏的处理,大致分为如下几种情况和思路:

也许,你不需要旋屏支持,而希望锁定屏幕

1 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
2 {
3     returnNO;
4 }

 

也许,你需要支持旋屏,或者支持部分方向的旋屏

1 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
2        return(interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
3 }

也许,你的view有张背景图,旋屏时系统帮助你拉伸了图片,但是却没有管你的其它部件,比如button,你希望直接改变button的大小和位置

01 -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
02 {
03     if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
04         NSLog(@"现在是竖屏");
05         [btn setFrame:CGRectMake(213, 442, 340, 46)];
06     }
07     if(UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
08         NSLog(@"现在是横屏");
09         [btn setFrame:CGRectMake(280, 322, 460, 35)];
10     }
11 }

 

也许,你并不希望用绝对坐标去约束控件,而是希望让它通过旋转自己适应屏幕的旋转

01 - (void)viewDidLoad
02 {
03     [super viewDidLoad];
04     // Do any additional setup after loading the view, typically from a nib.
05     UIDevice *device = [UIDevice currentDevice];
06     [device beginGeneratingDeviceOrientationNotifications];
07     //利用 NSNotificationCenter 获得旋转信号 UIDeviceOrientationDidChangeNotification
08     NSNotificationCenter *ncenter = [NSNotificationCenter defaultCenter];
09     [ncenter addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:device];
10 }
11  
12 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
13 {
14     return(interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
15 }
16  
17 -(void)rotation_btn:(float)n
18 {
19     UIButton *robtn = self.btn;
20     robtn.transform = CGAffineTransformMakeRotation(n*M_PI/180.0);
21 }
22  
23 -(void)orientationChanged
24 {
25     UIDeviceOrientation orientaiton = [[UIDevice currentDevice] orientation];
26      
27     switch(orientaiton) {
28         caseUIDeviceOrientationPortrait:            
29             [self  rotation_btn:0.0];
30             break;
31         caseUIDeviceOrientationPortraitUpsideDown: 
32             [self  rotation_btn:90.0*2];
33             break;
34         caseUIDeviceOrientationLandscapeLeft:    
35             [self  rotation_btn:90.0*3];
36             break;
37         caseUIDeviceOrientationLandscapeRight: 
38             [self  rotation_btn:90.0];
39             break;
40         default:
41             break;
42     }
43 }

也许,你需要autoresizesSubviews = YES

也许,你希望横竖屏有不同的布局效果,需要准备2份Subview,在不同状态去替换


 

当然不要忘记,需要调节设定图示中的1、2处
iOS开发 - 戏说旋屏

转自:http://blog.csdn.net/yiyaaixuexi/article/details/7670852 

 

抱歉!评论已关闭.