美文网首页
#iOS屏幕旋转

#iOS屏幕旋转

作者: ashura_ | 来源:发表于2017-05-28 21:29 被阅读0次

    测试环境

    • 软件环境
      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

    相关文章

      网友评论

          本文标题:#iOS屏幕旋转

          本文链接:https://www.haomeiwen.com/subject/eqghfxtx.html