#iOS屏幕旋转

测试环境

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

原理

支持的旋转方向

依赖Target设置

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

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类图

ClassDiagram1.jpg

push 形式Demo活动图

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

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容