IOS Other

聊聊iOS上屏幕旋转的那些坑

2017-06-22  本文已影响673人  _Choice_

前言

iOS的屏幕旋转可谓让人摸不着头脑,其中有历史原因也有设计原因。为了用户体验却大大增加了我们的开发难度。接下来聊聊屏幕旋转的坑。

大前提

iOS系统中,下拉控制台里有一个圆形锁,打开这个锁可以强制锁定屏幕旋转的方向。如果用户打开了这个圆形锁。无论你的App支持几个方向的旋转,都无法响应设备方向改变。
所以思路一下就清晰了。屏幕旋转总共两种情况

第一步设置App支持的方向

在开始一个工程,我们需要考虑到视图旋转是不是在整个App中都是全局支持的,以及支持的方向。例如有些iPad应用,支持全局的旋转视图。另外一种情况是,大多数时候我们只需要在某些页面,例如视频播放页面,去支持旋转。
全局设定支持的旋转页面有两种方法,第一种在工程设置里面,Device Orientantion中勾选支持的方向。

或者在AppDeleagate中用代码设置

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
   //返回你的app支持的旋转方向。
    return  XXX ;
}

具体实现

完成第一步的基本设置以后,我们根据之前提到过的两种情况来考虑具体的实现。

第一种情况,用户未开启锁定

用户在没有锁定的情况下,此时设备物理旋转后,App中会得到反馈。
收到一个旋转屏幕的通知:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(onDeviceOrientationChange)
                                             name:UIDeviceOrientationDidChangeNotification
                                           object:nil];

此时我们可以在通知回调里面去做响应的布局修改,适应横屏模式。

但现实中很多时候需求并不是这么简单。在iPhone上,大部分的App的大部分的页面并不支持旋转,而是在特定的页面,根据需要去旋转。
这个需求前提前面的设置只支持Portrait,
此时我们要通过在controller中重写以下几个方法,来绕过设置,在特定的页面去修改屏幕旋转的方向。

- (BOOL)shouldAutorotate {
    //确定你的控制器是否能够旋转(手动控制,或者自动旋转都要Return YES)
    return YES;
}

#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0
- (NSUInteger)supportedInterfaceOrientations {
#else
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
#endif
    //返回你的屏幕支持的方向
    return XXX;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    //你跳转(present)到这个新控制器时,按照什么方向初始化控制器
    return XXX;
}

也就是在特定的我们想让他能够旋转的页面中,去重写以上方法。
第三个方法可根据需要重写。

紧接着,这里有一个坑:当前页面的是否旋转,并不取决于当前页面的这三个方法(23333)
因为当前页面是否能够旋转,取决于window的root控制器,比如navigationcontroller,tabbarcontroller,
所以,来到window的root控制器中,去重写方法,记得根据实际情况做好判断,不然此控制器下的所有子页面就都支持旋转了。(2333)

也有另外一个方法就是通过category的形式,对navigationcontroller和tabbarcontroller进行扩展。

二者选其一吧,都能达到相同的目的。

到此,这种情况下,用户没有锁定,设备物理旋转,接受接收通知,响应旋转,实现,就完成。

第二种情况用户开启了锁定

事实上这种情况下,设备的物理旋转,App已经无法收到反馈,也就是你就算重写了那几个方法,也无法响应设备的旋转。
在这种情况下,我们就需要手动去旋转App的方向。
前提还是根据之前的重写那几个方法。
这是手动强制旋转的方法,私有API,但是商店能够过审,简直神奇。

if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
    SEL selector = NSSelectorFromString(@"setOrientation:");
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
    [invocation setSelector:selector];
    [invocation setTarget:[UIDevice currentDevice]];
    int val = UIInterfaceOrientationLandscapeRight;//这个方向即需要旋转到的那个方向,自行设置
    [invocation setArgument:&val atIndex:2];
    [invocation invoke];
}

同样的,在改变了屏幕方向以后,收到通知,然后做响应的操作即可。

总结

事实上,旋转存在的坑并不难,根据实际需求来做出修改是我们活学活用的目的。

上一篇下一篇

猜你喜欢

热点阅读