美文网首页
iOS横屏实践 2022-04-15 周五

iOS横屏实践 2022-04-15 周五

作者: 勇往直前888 | 来源:发表于2022-04-15 10:03 被阅读0次

    简介

    • 工程绝大多数界面只支持竖屏(大多数)

    • 其中的拍照界面只支持横屏(少数)

    工程配置

    • 理论上,工程配置是其效果的。通常的应用会配置为只支持竖屏。
      屏幕旋转在大多数情况下是个副作用,所以整体配置上需要禁止旋转。
    工程配置
    • 问题: 这样设置不起效果!!!
      原因: Info文件中增加了内容,没有改全。
    Info.plist

    代码配置

    • 工程Plist配置影响了初始化,在代码中可以进行修改覆盖。修改的地方在AppDelegate,只是以代理回调方法的形式存在,设置起来并不方便。

    *AppDelegate只有一个,并且系统提供了类似单例的访问方法,这为修改带来了方便。

    • 与工程配置相比,代码配置更加灵活。可以在特定的时候进行修改。

    • AppDelegate.h中提供一个属性供外部设置,修改。

    @interface AppDelegate : UIResponder <UIApplicationDelegate>
    
    // 与SceneDelegate中的window是同一个;
    // 很多第三方库,比如SVProgressHUD要用到;
    // 自己以view的方式做弹窗也要用到;
    @property (nonatomic, strong) UIWindow *window;
    
    // NO:只支持竖屏;YES:支持横屏(Home键在右)
    @property (nonatomic, assign) BOOL isLandscapeRight;
    
    @end
    
    • AppDelegate.m中修改配置
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
        
        // 默认不支持横屏,只支持竖屏
        self.isLandscapeRight = NO;
        
        return YES;
    }
    
    - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
        // 大多数情况只支持竖屏,少部分情况只支持横屏(Home键向右)
        if (self.isLandscapeRight) {
            return UIInterfaceOrientationMaskLandscapeRight;
        } else {
            return UIInterfaceOrientationMaskPortrait;
        }
    }
    

    旋转手机

    • AppDelegate.m中只是设置了xxxMask,代表了允许手机旋转的方向范围,并没有让手机实际旋转。

    • 旋转手机的APIUIDevice中,可是苹果并没有开发这个API,目前可以通过KVO的方式间接调用。

    这真的是很扯淡的事情。
    iOS强制改变物理设备方向的进阶方法

    // 旋转手机
    + (void)forceToOrientation:(UIDeviceOrientation)orientation {
        NSNumber *orientationTarget = [NSNumber numberWithInteger:orientation];
        [[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
    }
    
    • 实现旋转:要求Mask和实际的旋转动作相配套。不然的话没有效果。

    比如,你在AppDelegate.m设置只能竖屏的Mask,但是你却要求横屏向右旋转,结果当然是没效果。(自相矛盾啊)

    // 旋转到横屏
    + (void)rotateToLandscapeRight {
        // 先设置Mask
        AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
        appDelegate.isLandscapeRight = YES;
        
        // 然后旋转手机;方向需要在Mask的范围之内
        [PDADevice forceToOrientation:UIDeviceOrientationLandscapeRight];
    }
    
    // 旋转到竖屏
    + (void)rotateToPortrait {
        // 先设置Mask
        AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
        appDelegate.isLandscapeRight = NO;
        
        // 然后旋转手机;方向需要在Mask的范围之内
        [PDADevice forceToOrientation:UIDeviceOrientationPortrait];
    }
    

    调用时机

    由于绝大多数页面只需要竖屏就可以了,这个只要在工程配置的地方配置一下就行。
    对于需要横屏的页面,可以在viewWillAppear中设置为横屏,然后在viewWillDisappear中设置为竖屏就可以了。

    - (void)viewWillAppear:(BOOL)animated {
        /*
         * 设置横屏
         */
        [PDADevice rotateToLandscapeRight];
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        /*
         * 设置竖屏
         */
        [PDADevice rotateToPortrait];
    }
    

    参考文章

    iOS固定APP 某个界面强制横屏或者竖屏

    iOS强制改变物理设备方向的进阶方法

    iOS 不勾选设置工程Landscape,实现某个界面强制横屏

    iOS设置某个界面强制横屏,进入就横屏

    失效的屏幕旋转方法

    • 很多文章都说重写下面几个方法,可以实现屏幕旋转。可是实际试过之后才知道并不可行。
    - (BOOL)shouldAutorotate {
        return NO; // 注意:如果是只支持一种,比如只支持横屏,这里需要设置为NO;YES的至少需要两种或者以上的Mask才行。
    }
    
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskLandscapeRight;
    }
    
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
        return UIInterfaceOrientationLandscapeRight;
    }
    
    • 之所以要通过重写getter方法的方式来实现修改的目的,是因为UIViewController的这3个属性是只读的。
    // New Autorotation support.
    @property(nonatomic, readonly) BOOL shouldAutorotate API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
    @property(nonatomic, readonly) UIInterfaceOrientationMask supportedInterfaceOrientations API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
    // Returns interface orientation masks.
    @property(nonatomic, readonly) UIInterfaceOrientation preferredInterfaceOrientationForPresentation API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
    
    • 如果是present出来的界面,上面的设置是可以起效果的。

    • 如果是Navigation Controller管理,push(show)出来的界面,上面那样设置是不起效果的。因为Navigation Controller是容器,UIViewContainer是容器里的物品。容器和物品的方向要一致才能起效果。
      所以,导致大部分时候,上面这些代码不起作用,估计大概率的原因是两者不匹配导致的。

    吐槽

    • 旋转屏幕,固定屏幕朝向,直观上应该是很简单的一个功能,但是实际用下来,却要用到黑科技(KVO)。这不得不让人吐槽苹果真不厚道。

    • 就算是通过属性设置,却提供好几个“只读”属性,并且要好几个属性配合起来才行。

    • 更夸张的是设定当前UIViewContainer的朝向,还竟然要考虑容器Navigation Controller的朝向,还要保证两者一致才有可能起效果。

    • 这样搞,要么就是存心不让人使用改变屏幕朝向的API;要么就是设计这些个API的人是蠢货。苹果工程师出蠢货也不是一两个例子了。

    相关文章

      网友评论

          本文标题:iOS横屏实践 2022-04-15 周五

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