iOS:关于横竖屏切换的知识点

iOS16横竖屏的切换有了新的方式,正好赶上新的项目要求,所以重新整理了一下项目中的横竖屏切换问题。
项目要求:

  • iPhone整体禁止屏幕旋转只能竖屏,某些特定页面强制横屏,某些页面可以自由旋转。
  • iPad整体可以自由旋转,某些页面可以强制切换横竖屏,且切换后当前页面关闭自由旋转,返回后开启自由旋转。

如何开始横竖屏切换

1、项目配置:

在Xcode中TARGETS - General - Deployment Info中设置支持的方向,例如iPhone设置只支持竖屏,iPad支持全方向,注意iPad情况下需要勾选Requires full screen,设置为全屏,不分屏,否则强制切换屏幕旋转将失效(自己发现的,没有找到相关解释,有大神也可以解释一下)。如果不配置,只通过AppDelegate中代理方法控制,会导致启动页时不能正常识别屏幕方向。

Xcode配置.jpg

2、AppDelegate中的设置

因为某些页面需要强制屏幕切换,所以通过在AppDelegate实现代理的方式控制.
AppDelegate.h

/// 通过AppDelegate是实现旋转,解决部分页面强制旋转
/// 屏幕支持的方法方向
@property (nonatomic, assign) UIInterfaceOrientationMask orientations;

AppDelegate.m

  1. application:didFinishLaunchingWithOptions:中设置默认方向
// 设置默认方向
if (isPad) {
  // ipad
  self.orientations = UIInterfaceOrientationMaskAll;
} else {
  self.orientations = UIInterfaceOrientationMaskPortrait;
}
  1. 实现代理方法
/// 切换横竖屏:返回支持方向
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return self.orientations;
}
  1. 强制切换方向,且切换后禁止旋转
    例如强制横屏如下
 // AppDelegate设置横屏
    AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;

    // 当前是否横屏
    if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft || [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) {
        // 已经横屏,AppDelegate中锁定为当前屏幕状态
        app.orientations = (1 << [UIApplication sharedApplication].statusBarOrientation);
    } else {
        // 竖屏-强制屏幕横屏
        // AppDelegate中锁定为横屏
        app.orientations = UIInterfaceOrientationMaskLandscapeRight;
        // 强制旋转
        if (@available(iOS 16.0, *)) {
#if defined(__IPHONE_16_0)
            // 避免没有更新Xcode14的同事报错
            // iOS16新API,让控制器刷新方向,新方向为上面设置的orientations
            [self setNeedsUpdateOfSupportedInterfaceOrientations];
#endif
        } else {
            // iOS16以下
            NSNumber *orientationPortrait = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
            [[UIDevice currentDevice] setValue:orientationPortrait forKey:@"orientation"];
        }
    }

在适当的位置记得iPhone修正方向,iPad放开旋转
        // iPhone改为竖屏,具体方式参考横屏
        // pad放开屏幕方向
        AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
        app.orientations = UIInterfaceOrientationMaskAll;
  1. 某个页面放开横竖屏切换,比如全屏视频播放时。
// 放开
AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
app.orientations = UIInterfaceOrientationMaskAll;
// 锁定
AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
app.orientations = UIInterfaceOrientationMaskPortrait;

#这种情况下,iOS16的强制横竖屏切换需要添加代码设置强制旋转,例如:
// 强制屏幕竖屏:手机
if ([UIApplication sharedApplication].statusBarOrientation != UIInterfaceOrientationPortrait) {
    if (@available(iOS 16.0, *)) {
        // iOS16新API,让控制器刷新方向,新方向为上面设置的orientations
#if defined(__IPHONE_16_0)
        [self setNeedsUpdateOfSupportedInterfaceOrientations];
        NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
        UIWindowScene *scene = [array firstObject];
        // 屏幕方向
        UIInterfaceOrientationMask orientation = UIInterfaceOrientationMaskPortrait;
        UIWindowSceneGeometryPreferencesIOS *geometryPreferencesIOS = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:orientation];
        // 开始切换
        [scene requestGeometryUpdateWithPreferences:geometryPreferencesIOS errorHandler:^(NSError * _Nonnull error) {
            NSLog(@"强制%@错误:%@", @"横屏", error);
        }];
#endif
     } else {
          // iOS16以下
          NSNumber *orientationPortrait = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
          [[UIDevice currentDevice] setValue:orientationPortrait forKey:@"orientation"];
      }
}
  1. 关于横竖屏切换的监听
    对于屏幕旋转的监听,建议监听UIApplicationDidChangeStatusBarOrientationNotification,及状态栏的方向变化通知,这个收到这个通知的时候说明页面UI已经切换了。例如:
// 横竖屏切换通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleScreenOrientationChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
/// 横竖屏切换通知
- (void)handleScreenOrientationChange:(NSNotification *)noti {
    if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait || [UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationPortraitUpsideDown) {
        // 竖屏
    } else {
        // 横屏
    }
}
注意判断屏幕方向的时候一定要用UIInterfaceOrientation:屏幕的方向,不要错误的使用的UIDeviceOrientation:设备的方向。

暂时就这些内容。

补充一点,写代码的时候能用Autolayout就尽量用,不然突然有一天让你整个App适配横竖屏切换,在原有手机端代码基础上开发Pad,还有分屏效果,哭都没地方。

你可能感兴趣的:(iOS:关于横竖屏切换的知识点)