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

简介

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

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

工程配置

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

代码配置

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

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

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

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

@interface AppDelegate : UIResponder 

// 与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 周五)