#iOS屏幕旋转

测试环境

  • 软件环境
    iOS9,Xcode7.3
  • 时间
    2016-12-13

原理

支持的旋转方向

依赖Target设置

默认工程支持三种方向,不支持倒置

#iOS屏幕旋转_第1张图片
TSInterfaceOrientation_xcodeproj.png

依赖UIApplicationDelegate

APP首先调用 UIApplicationDelegateapplication: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.


通常情况下,系统探知旋转事件,而后通过WindowRootCOntroller逐级向下传递旋转事件。
Demo类图

#iOS屏幕旋转_第2张图片
ClassDiagram1.jpg

push 形式Demo活动图

#iOS屏幕旋转_第3张图片
ActivityDiagram1.jpg
  • Push形式的旋转是静态的,即在程序运行时候,就确定了方向。默认情况下,这一套流程只走一遍,最底层的controller(TSDemoViewController)的对应方法并不会在每次push时候调用。
  • present形式的旋转是动态的,并且显示的方向是最底层的viewController设置的方向。

push形式

  • PushController会以最上层Controller最小纬度,来显示当前Controller

以Demo为例:

Present形式

代码

  • supportedInterfaceOrientationspreferredInterfaceOrientationForPresentation必须对应,否则崩溃,包括对应的父Controller,presentController会在进入时候崩溃,父Controller会在DisMiss时候崩溃。
  • 必须实现preferredInterfaceOrientationForPresentation,不然无法按照预期显示。
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeLeft;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationLandscapeLeft;
}

-(BOOL)shouldAutorotate {
    return YES;
}

如果代码没错,但是还是旋转无效。请注意系统设置是否锁定了

#iOS屏幕旋转_第4张图片
ScreenShot_20161214113450.png

强制转屏

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];
    }];
}

Demo

TSInterfaceOrientation

你可能感兴趣的:(#iOS屏幕旋转)