测试环境
- 软件环境
iOS9
,Xcode7.3
- 时间
2016-12-13
原理
支持的旋转方向
依赖Target设置
默认工程支持三种方向,不支持倒置
依赖UIApplicationDelegate
APP
首先调用 UIApplicationDelegate
的application:supportedInterfaceOrientationsForWindow:
来判断支持的方向。
关键方法
关于这个Delegate
application:supportedInterfaceOrientationsForWindow:
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.
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
Override this method to report all of the orientations that the view controller supports. The default values for a view controller'��s supported interface orientations is set to UIInterfaceOrientationMaskAll for the iPad idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom.
- (BOOL)shouldAutorotate
YES if the content should rotate, otherwise NO. This method returns YES by default.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
The system calls this method when presenting the view controller full screen. When your view controller supports two or more orientations but the content appears best in one of those orientations, override this method and return the preferred orientation.
If your view controller implements this method, your view controller’s view is shown in the preferred orientation (although it can later be rotated to another supported rotation). If you do not implement this method, the system presents the view controller using the current orientation of the status bar.
通常情况下,系统探知旋转事件,而后通过Window
的RootCOntroller
逐级向下传递旋转事件。
Demo类图
push 形式Demo活动图
- Push形式的旋转是
静态的
,即在程序运行时候,就确定了方向。默认情况下,这一套流程只走一遍,最底层的controller(TSDemoViewController
)的对应方法并不会在每次push时候调用。 - present形式的旋转是
动态的
,并且显示的方向是最底层的viewController设置的方向。
push形式
-
PushController
会以最上层Controller
的最小纬度
,来显示当前Controller
以Demo为例:
Present形式
代码
-
supportedInterfaceOrientations
与preferredInterfaceOrientationForPresentation
必须对应,否则崩溃,包括对应的父Controller
,presentController
会在进入时候崩溃,父Controller
会在DisMiss时候崩溃。 - 必须实现
preferredInterfaceOrientationForPresentation
,不然无法按照预期显示。
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeLeft;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
-(BOOL)shouldAutorotate {
return YES;
}
如果代码没错,但是还是旋转无效。请注意系统设置是否锁定了
强制转屏
push形式的Controller跟present形式的Controller强制转评的方法是不一样的。
Push强制转屏
使用的是黑科技,还要注意要逐层
进行转换,否则不起作用。
具体可看Demo自行分析
- (void)forceLandscapeLeft
{
JinnNavigationController *navigationController = (JinnNavigationController *)self.navigationController;
[navigationController changeSupportedInterfaceOrientations:UIInterfaceOrientationMaskLandscapeLeft];
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 = UIInterfaceOrientationLandscapeLeft;
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
}
present强制转屏
实际上是手动对View进行旋转
- (void)forceLandscapeLeft
{
CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration;
[UIView animateWithDuration:duration animations:^{
self.view.transform = CGAffineTransformMakeRotation(-M_PI_2);
self.view.bounds = CGRectMake(0, 0, MAX_SCREEN_SIDE, MIN_SCREEN_SIDE);
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
}];
}