ios的横竖屏适配

1.横竖屏方向枚举

关于横竖屏一共有三种枚举,UIInterfaceOrientation,UIInterfaceOrientationMask,UIDeviceOrientation。

1.1 UIInterfaceOrientation与UIDeviceOrientation

为什么这两个放在一起说,好吧,你看看下面这个枚举定义:

typedefNS_ENUM(NSInteger,UIInterfaceOrientation) {UIInterfaceOrientationUnknown=UIDeviceOrientationUnknown,UIInterfaceOrientationPortrait=UIDeviceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown=UIDeviceOrientationPortraitUpsideDown,UIInterfaceOrientationLandscapeLeft=UIDeviceOrientationLandscapeRight,UIInterfaceOrientationLandscapeRight=UIDeviceOrientationLandscapeLeft}

我相信你应该看出了点东西了把,对于iOS设备来讲,屏幕状态由以上五种状态。上下翻转还是很好区分的,左右旋转可能就不是很好区分。

这里有个坑!!!

高能预警:

请仔细观察上面的枚举值。

在处于竖屏和上下翻转的状态下这两个枚举值是一样的,而当处于横屏时,这两个值刚好相反。

所以在有时你发现跟你预期的翻转方向不一样的时候,可能你用错了枚举。

UIDeviceOrientation是设备的当前所处的方向,而且事实上它有6个值,

typedefNS_ENUM(NSInteger,UIDeviceOrientation) {UIDeviceOrientationUnknown,UIDeviceOrientationPortrait,// Device oriented vertically, home button on the bottomUIDeviceOrientationPortraitUpsideDown,// Device oriented vertically, home button on the topUIDeviceOrientationLandscapeLeft,// Device oriented horizontally, home button on the rightUIDeviceOrientationLandscapeRight,// Device oriented horizontally, home button on the leftUIDeviceOrientationFaceUp,// Device oriented flat, face upUIDeviceOrientationFaceDown// Device oriented flat, face down}

分别对应iPhone未知方向,竖直,上下反转,向左旋转,向右旋转,屏幕朝上,屏幕朝下。关于横屏如何去分左右,其实API中的注释已经说明,当处于UIDeviceOrientationLandscapeLeft,home键在右侧,当处于UIDeviceOrientationLandscapeRight,home键在左侧。

所以,UIDevice顾名思义,事实上是用来判断设备方向的。

UIInterfaceOrientation即当前页面的方向。

在设备进行横屏旋转的时候,为了横屏时上下不翻转,所以当Device处于Left时,界面应该是Right旋转。这样才不会使横屏时内容上下翻转。所以我想你应该明白了为什么在处于横屏时为什么他们俩的值是刚好相反的。

所以对于横竖屏适配,使用的枚举大家一定要看好,使用UIInterfaceOrientation。不要搞反。

1.2 UIInterfaceOrientationMask

其实苹果大大还是给了我们更清晰和方便的枚举如下:

typedefNS_OPTIONS(NSUInteger,UIInterfaceOrientationMask) {UIInterfaceOrientationMaskPortrait= (1<

事实上我们在横竖屏适配时,最常用的是这个枚举。这个枚举详细的列举了各种你需要的情况。我就不赘述了。官方的命名还是很舒服很好理解的。

2.开启横竖屏权限

开启横竖屏的方式有两种,一种是在项目中直接进行勾选,

ios的横竖屏适配_第1张图片

image 1

可以看到这种勾选方式允许你进行四个方向的配置,并且这种勾选方式会直接在你的项目plist文件中添加

image 2

但是由于在这里配置是对项目启动时lanuch界面产生影响,而往往我们又没有对lanuch进行横竖屏适配,所以在这个时候我们就需要使用第二种方式进行配置。

在项目中的AppDelegate文件中进行配置。

#pragma mark - InterfaceOrientation //应用支持的方向- (UIInterfaceOrientationMask)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window {returnUIInterfaceOrientationMaskAllButUpsideDown;}

搭配UIInterfaceOrientationMask使用,你可以很方便的让你项目开启你所需要的横竖屏权限和限制条件。

3.在VC中如何控制横竖屏

我们都知道MVC架构,那么显而易见,在我们开启了项目的横竖屏的限制之后,需要在ViewController进行相应的配置,才能真正实现横竖屏。

开启横竖屏,我们需要在VC中添加如下代码:

// 设备支持方向- (UIInterfaceOrientationMask)supportedInterfaceOrientations {returnUIInterfaceOrientationMaskAll;}// 默认方向- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {returnUIInterfaceOrientationPortrait;// 或者其他值 balabala~}

而对于横竖屏,手机端一般有两种情况,一种是手机没有开启横竖屏锁定,用户将手机横屏时触发的。对于第一种情况,我们只需要在VC中添加:

// 开启自动转屏- (BOOL)shouldAutorotate {returnYES;}

另一种是我们在项目中的某些条件下强行让屏幕横屏,例如大图预览,视频播放,等等。而对于这种情况,我们可以使用下面这两种方法,都可以实现效果:

- (void)setInterfaceOrientation:(UIInterfaceOrientation)orientation {if([[UIDevicecurrentDevice] respondsToSelector:@selector(setOrientation:)]) {        SEL selector =NSSelectorFromString(@"setOrientation:");NSInvocation*invocation = [NSInvocationinvocationWithMethodSignature:[UIDeviceinstanceMethodSignatureForSelector:selector]];        [invocation setSelector:selector];        [invocation setTarget:[UIDevicecurrentDevice]];intval = orientation;        [invocation setArgument:&val atIndex:2];        [invocation invoke];    }}

- (void)setInterfaceOrientation:(UIDeviceOrientation)orientation {if([[UIDevicecurrentDevice] respondsToSelector:@selector(setOrientation:)]) {        [[UIDevicecurrentDevice] setValue:[NSNumbernumberWithInteger:orientation] forKey:@"orientation"];    }}

PS:这两个方法只有在- (BOOL)shouldAutorotate( return YES; )时,才会生效。并且请注意使用的枚举值的不同。

4.横竖屏控制优先级

在我们接手一个项目后,说要添加一个某个界面横竖屏需求时,发现按照上面的方式配置了一圈,发现还是转!不!成!功!What F***!!!

事实上在这里我们要了解一个问题,就是关于横竖屏控制的优先级。对于限于VC范围来讲优先级最高的是当前的window的rootViewController,而往往我们的项目结构是容器视图控制器控制VC,tabBarController控制navigationController之后是VC,而横竖屏控制的优先级也是跟你的项目架构一样。而且是一旦优先级高的关闭了横竖屏配置,优先级低的无论如何配置都无法做到横竖屏。所以在你接受这个需求的时候,你需要看一下根视图的配置。

对于这种情况,我们有两种处理方式,一种是通过模态的方式跳转的下个VC,这个VC是隔离出来的,不在你之前的容器里,不会受到rootViewController的影响。

而另一种我们需要改造一下根视图的配置:

-(BOOL)shouldAutorotate {return[[self.viewControllers lastObject] shouldAutorotate];  }  - (UIInterfaceOrientationMask)supportedInterfaceOrientations {return[[self.viewControllers lastObject] supportedInterfaceOrientations];  }  - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {return[[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];  }

或者

-(BOOL)shouldAutorotate {if([[self.viewControllers lastObject]isKindOfClass:[NewViewControllerclass]]) {returnYES;    }returnNO;}- (UIInterfaceOrientationMask)supportedInterfaceOrientations {if([[self.viewControllers lastObject]isKindOfClass:[NewViewControllerclass]]) {returnUIInterfaceOrientationMaskLandscapeLeft;    }returnUIInterfaceOrientationMaskPortrait;}- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {if([[self.viewControllers lastObject]isKindOfClass:[NewViewControllerclass]]) {returnUIInterfaceOrientationLandscapeLeft;    }returnUIInterfaceOrientationPortrait;}

可以看到我们通过获取push栈中的最后一个VC的属性,或指定特殊的VC来进行rootViewController的横竖屏设置。

当然也可以通过NSNotificationCenter或者NSUserDefaults的方式对这里的值进行设置,在这里我就不过多赘述了。

总之要知道优先级的问题,general==appDelegate>>rootViewController>>nomalViewController

明白了权限的优先级以及开启的方法我想转屏就很显而易见了。

5.横竖屏适配

事实上旋转屏幕成功,对于iOS横竖屏问题我们只是完成了一半。另一半就是UI适配问题,其实这个要说起来就比较麻烦了,有些时候有很多case需要针对对应的业务条件来定制。但是无外乎几种实现思路。这里博主给大家抛几块砖哈:

首先我们要知道,当发生转屏事件时,系统的回调方法是:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator {if(size.width > size.height) {// 横屏// 横屏布局 balabala}else{// 竖屏布局 balabala}}

首推的方式是使用约束布局,在使用约束布局时,横竖屏转换时,在通常情况下约束条件会很相似,所以在布局上会极大的减少代码量。其次如果有个别的特殊问题,可以在上面的回调方法里面进行微调。

其次,对于转屏后,[UIScreen mainScreen].bounds.size以及self.view.frame.size的宽高系统会自动调换。即在横屏的时候width > height。所以在我们进行常规布局的时候我们可以选择控件的frame属性都与这两个属性进行比例换算。这样在当横竖屏转换的时候,重布局时,也会适应成对应屏幕下的布局。同样有需要特殊处理的布局,在上面的回调方法中进行细节微调即可。

对于子视图,在横竖屏切换时,会触发子视图重布局的方法:

- (void)layoutSubviews {    [superlayoutSubviews];// 通过状态栏电池图标来判断屏幕方向if([UIApplicationsharedApplication].statusBarOrientation ==UIInterfaceOrientationMaskPortrait) {// 竖屏 balabala}else{// 横屏 balabala}}

你可能感兴趣的:(ios的横竖屏适配)