一、屏幕旋转机制:
iOS通过加速计判断当前的设备方向和屏幕旋转。当加速计检测到方向变化的时候,屏幕旋转的流程如下:
1、设备旋转时,系统接收到旋转事件。
2、系统将旋转事件通过AppDelegate通知当前的主Window。
3、window通知它的rootViewController。
4、rootViewController判断所支持的旋转方向,完成旋转。
iOS系统中屏幕旋转事件没有像触碰事件那样进行hitTest,所以只有rootViewController才能接收到屏幕旋转的事件,在其他viewController中实现旋转控制方法是不会被调用的。当屏幕旋转时应用程序会发出UIDeviceOrientationDidChangeNotification通知,这样任何关系方向变化的view都可以通过注册该通知,在设备方向发生变化的时候发生响应。
在响应设备旋转时,我们可以通过UIViewController的方法实现更细粒度的控制,当view controller接收到window传来的方向变化的时候,流程如下:
1、首先判断当前viewController是否支持旋转到目标方向,如果支持则继续,否则流程就此结束。
2、调用 willRotateToInterfaceOrientation:duration:
方法,通知view controller将要旋转到目标方向。如果该viewController是一个container view controller的话,它会继续调用其content view controller的该方法。这个时候我们也可以暂时将一些view隐藏掉,等旋转结束以后在现实出来。
3、window调整显示的view controller的bounds,由于view controller的bounds发生变化,将会触发 viewWillLayoutSubviews 方法。这个时候
interfaceOrientation和statusBarOrientation方向还是原来的方向。
4、接着当前view controller的 willAnimateRotationToInterfaceOrientation:duration:
方法将会被调用。系统将会把该方法中执行的所有属性变化放到animation block中。
5、执行屏幕旋转动画。
6、最后调用 didRotateFromInterfaceOrientation:
方法,通知view controller旋转动画执行完毕。这个时候我们可以将第二部隐藏的view再显示出来。
整个响应过程如下图所示:
以上就是UIKit下一个完整的屏幕旋转流程,我们只需要按照提示做出相应的处理就可以完美的支持屏幕旋转。
二、旋转机制实现
iOS5屏幕旋转控制
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return YES; }
返回YES就是允许旋转,NO就是不允许
根据toInterfaceOrientation 可以控制屏幕允许旋转的方向,比如不支持Home按钮朝上这种屏幕方向。代码如下:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { if (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) { return NO; } return YES; }
这种方法已经被苹果列为deprecated。但为了兼容iOS5及以前的版本还需要继续实现。
iOS6屏幕旋转控制
- (BOOL)shouldAutorotate 默认返回YES,当为YES时允许转屏,否则为不允许。
- (NSUInteger)supportedInterfaceOrientations 决定可以转哪个方向。如果所有方向都支持返回 UIInterfaceOrientationMaskAll,如果不允许Home键朝上返回UIInterfaceOrientationMaskAllButUpsideDown。
三、注意事项
1、旋屏后的frame