IOS7 到IOS8 一个通用的横竖屏幕切换总结

来源:互联网 发布:1=1 sql注入步骤 编辑:程序博客网 时间:2024/05/18 02:49

IOS7 到IOS8 一个通用的横竖屏幕切换总结

以下内容是在IOS7和IOS8系统验证得到的结论

1.首先,在iOS8之前的[UIScreenmainScreen].bounds和 [UIScreen mainScreen].applicationFrame两者的区别在于:

1)[UIScreenmainScreen].bounds:指固定的屏幕尺寸(宽高固定)

2)[UIScreenmainScreen].applicationFrame:指除却状态栏后的固定的屏幕尺寸

比如对于 iPhone4而言,无论屏幕怎么旋转 [UIScreen mainScreen].bounds都是固定的(0,0,320,480); [UIScreenmainScreen].applicationFrame都是固定的(0,20,320,460);

 

2.但是在iOS8 中[UIScreenmainScreen].bounds 和 [UIScreen mainScreen].applicationFrame两者不再是固定不变的。

当旋转的时候,屏幕也会发生改变。/////这是在iOS8中影响选择适配的一个原因。

    iOS 7之前Window的bounds不会随着方向而变化,但是到了iOS 8以后,随着设备方向的旋转,window.bounds.size.width和window.bounds.size.height也会相应发生变化。

   同样受影响的还有键盘弹起和消失的通知中[[[notificationuserInfo] objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue]的值,iOS7是以没有旋转的window坐标系为标准计算的,而iOS8是以旋转后的window坐标系为标准计算的。

   还有[UIApplicationsharedApplication].statusBarFrame的尺寸也是同样的道理。

XCode6 +iOS8SDK+iOS8设备:

iPad横屏情况下

[[UIScreen mainScreen] bounds]:{{0, 0},{1024, 768}}

[[UIScreen mainScreen]applicationFrame:{{0, 20}, {1024, 748}}

iPad竖屏情况下

[[UIScreen mainScreen] bounds]:{{0, 0},{768, 1024}}

[[UIScreen mainScreen]applicationFrame:{{0, 20}, {768, 1004}}

 

XCode5 +iOS7SDK+iOS7设备(或者XCode6+iOS8SDK+iOS7)
iPad横屏情况下
[[UIScreenmainScreen] bounds]:{{0, 0}, {768, 1024}}
[[UIScreen mainScreen]applicationFrame:{{20, 0}, {748, 1024}}
iPad竖屏情况下
[[UIScreenmainScreen] bounds]:{{0, 0}, {768, 1024}}
[[UIScreen mainScreen]applicationFrame:{{0, 20}, {768, 1004}}

 

XCode6 +iOS8SDK+iOS8设备:

iPhone横屏情况下
[[UIScreenmainScreen] bounds]:{{0, 0}, {568, 320}}
[[UIScreen mainScreen]applicationFrame:{{0, 0}, {568, 320}}

[[notificationuserInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue] keyboardWillShow: {{0,127}, {568, 193}}

iPhone竖屏情况下
[[UIScreenmainScreen] bounds]:{{0, 0}, {320, 568}}
[[UIScreen mainScreen]applicationFrame:{{0, 20}, {320, 548}}

[[notificationuserInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue] keyboardWillShow:{{0, 315}, {320, 253}}

 

XCode5 +iOS7SDK+iOS7设备(或者XCode6+iOS8SDK+iOS7)

iPhone横屏情况下

[[UIScreen mainScreen] bounds]:{{0, 0},{320, 568}}

[[UIScreen mainScreen]applicationFrame:{{0, 0}, {300, 568}}

[[notificationuserInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue] keyboardWillShow: {{158,0}, {162, 568}}

iPhone竖屏情况下
[[UIScreenmainScreen] bounds]:{{0, 0}, {320, 568}}
[[UIScreen mainScreen] applicationFrame:{{0,20}, {320, 548}}

[[notificationuserInfo][UIKeyboardFrameEndUserInfoKey]CGRectValue] keyboardWillShow: {{0, 264}, {320, 216}}

如果代码中有依赖UIScreenbounds属性、UIWindowbounds属性、键盘通知中UIKeyboardFrameEndUserInfoKey值、[UIApplication sharedApplication].statusBarFrame的地方,那么在用XCode6+iOS8SDK发布新版本前就要高度注意了

 

 

 

ios 旋转问题分强制和非强制2种大情况:

1、       众所周知,在我们的工程设置中有横竖屏的设置选项如下图:

如果只勾选Portrait则整个工程只支持竖屏,所有的界面都不能旋转,即使使用了像这样的强制旋转代码[[UIDevice currentDevice] setValue:[NSNumbernumberWithInteger:UIDeviceOrientationLandscapeLeft] forKey:@"orientation"];也无济于事。

那么对于一个工程只有个别界面需要旋转只勾选Portrait当然是不能旋转的,如果打开LandscapeRightLandscapeLeft那整个工程都旋转了,就达不到只让个别界面旋转的目地。其实,对于这种情况一般人的做法是弄个UINavigationController然后

-(NSUInteger)supportedInterfaceOrientations

{

   return [self.topViewController supportedInterfaceOrientations];

}

- (BOOL)shouldAutorotate

{

   return [self.topViewController shouldAutorotate];

}

可以解决问题!不过这样做可能为以后留下坑(其他界面忘记做处理出现界面混乱现象)。对于这种个别界面旋转情况其实完全可以这样做:就是只勾选Portrait则整个工程只支持竖屏。也不用弄什么UINavigationController然后,直接在AppDelegate中实现这个方法:

- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow *)window

{

   //if([[self.window.rootViewController.navigationController.viewControllerslastObject] isKindOfClass:[PlayViewController class]])

   if(self.makeOrientation == UIInterfaceOrientationLandscapeRight)

    {

       return UIInterfaceOrientationMaskLandscapeRight;

    }

   else

    {

       return UIInterfaceOrientationMaskPortrait;

    }

}

即可!注意:self.makeOrientation属性是一个全局的目地就是以后方便哪个界面要旋转就设置成相应的旋转枚举。我一般是在点击事件触发的时候设置一下,再取消旋转的触发事件再次恢复设置。推动界面旋转的方法有2种,第一种:[[UIDevice currentDevice] setValue:[NSNumbernumberWithInteger:UIDeviceOrientationLandscapeLeft]forKey:@"orientation"];

第二种:   

if ([[UIDevice currentDevice]respondsToSelector:@selector(setOrientation:)]) {

       SEL selector = NSSelectorFromString(@"setOrientation:");

       NSInvocation *invocation = [NSInvocationinvocationWithMethodSignature:[UIDeviceinstanceMethodSignatureForSelector:selector]];

       [invocation setSelector:selector];

       [invocation setTarget:[UIDevice currentDevice]];

       int val = UIInterfaceOrientationLandscapeRight;

       [invocation setArgument:&val atIndex:2];

       [invocation retainArguments];

       [UIViewController attemptRotationToDeviceOrientation];

       [invocation invoke];

}苹果都可以审核通过。而此时没有使用任何shouldAutorotate  supportedInterfaceOrientations方法。

所以现在的问题是:有了方法supportedInterfaceOrientationsForWindow什么时候用shouldAutorotate  supportedInterfaceOrientations方法?还会起作用吗?他们俩是什么关系?至今没有发现。

还有一个地方需要注意:实现了方法supportedInterfaceOrientationsForWindow后就屏蔽了工程设置选项。也就是说,此时那4个单选框无论怎么勾选都不起作用了,整个工程界面的旋转都以这个方法为切入点。无论工程设置成什么样,有没有实现shouldAutorotate  supportedInterfaceOrientations方法,任何时候执行强制旋转或往东南西北转动设备这个方法都会回调的,仔细观察发现这个方法的实现返回的枚举值都必须是带有Mask的字样,这个Mask起位掩码的作用,它是基于currentDevice的方向Orientation值做相应的旋转变化,将要设置的位和当前设备的方向位做位掩。比如:当前设备(home键)的方向已经和你设置的旋转UIDeviceOrientationLandscapeLeft方向一致了,那你触发旋转的时候界面不动还是此时的方向,相反如果你的(home键)的方向和要设置的方向不一样那界面会做旋转变化不一定都是旋转90°。

有的人说这个方法只对于present出来的界面起作用,那是不完全正确,因为官方说了This method returns the total set of interfaceorientations supported by the app. When determining whether to rotate aparticular view controller, the orientations returned by this method areintersected with the orientations supported by the root view controller ortopmost presented view controller. The app and view controller must agreebefore the rotation is allowed.

这是我设置的pushViewController截图如下

所以照样可以旋转。官方还 说了If you do not implement this method, the app uses the values in the UIInterfaceOrientation key of the app’s Info.plist as the default interface orientations.如果没有实现这个方法旋转的时候就去从工程设置取值来呈现相应方向的界面,这也就是前面说的实现这个方法会屏蔽工程设置。

对于做视频横屏播放的情况下:做旋转有3种方法。

第一种:就是网上说的用旋转矩阵方法CGAffineTransformMakeRotation来做,直接旋转某个view,之后setFrame,至于状态栏,全屏横屏之后就隐藏吧。这种方法有个弊端是音量图标不能随着一起旋转,QA到时候会挑BUG。

第二种:就是打开工程设置前面也说了弄个导航控制器。

第三种:就是前面说的- (NSUInteger)application:(UIApplication *)applicationsupportedInterfaceOrientationsForWindow:(UIWindow *)window方法。

这三种方法各有特点,对于多界面横屏适合第二种方法,对于个别界面横屏适合第三种方法。

0 0
原创粉丝点击