IOS16横竖屏适配

本文介绍了如何在iOS16及更高版本中,从使用AppDelegate控制屏幕旋转的传统方式转变为使用UIWindowSceneAPI进行更现代的横竖屏切换管理。作者详细展示了在新版本中如何处理界面布局更新以及错误回调的处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说新版本之前先了解下旧版本的适配,直接上代码:(我们公司的项目是根据按钮强制横竖屏的)

1.在AppDelegate类上这个方法:根据按钮设置做出响应

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{

    UIDevice *device = [UIDevice currentDevice];

    if (!_shouldRotate||device.orientation == UIDeviceOrientationPortraitUpsideDown){

        return UIInterfaceOrientationMaskPortrait;

    }else{

        return UIInterfaceOrientationMaskLandscapeLeft;

    }

}

2.在点击按钮的ViewController类中写下列方法

- (void)clickScreenBtn:(UIButton*)btn{

    //放大

    btn.selected = !btn.selected;

    if (btn.selected) {//放大

        AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;

        delegate.shouldRotate = YES;

        NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationLandscapeLeft];

        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];

    }else{//还原

        AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;

        delegate.shouldRotate = NO;

        NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];

        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];

    }

}

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator{

    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    kWSelf(self)

    if (size.width>size.height) {//横屏

        self.navigationController.navigationBar.hidden = YES;

        [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {

            //更新view的位置与大小 下面是我的界面可以换成你自己的

            weakself.playerView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);

            weakself.avLayer.frame = weakself.playerView.bounds;

            weakself.toolBarView.frame = CGRectMake(0, kScreenHeight-40, kScreenWidth, kScreenHeight-40);

            weakself.infoView.hidden = YES;

        }];

    }else{

        self.navigationController.navigationBar.hidden = NO;

        [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context){

            //更新view的位置与大小 下面是我的界面可以换成你自己的

            weakself.playerView.frame = CGRectMake(0, 0, kScreenWidth, 250);

            weakself.avLayer.frame = weakself.playerView.bounds;

            weakself.toolBarView.frame = CGRectMake(0, 210, kScreenWidth, 40);

            weakself.infoView.hidden = NO;

        }];

    }

}

4.以上是旧版本的,从IOS16.0开始苹果更改了屏幕的旋转机制,以后都要用UIWindowScene api的类

// 获取当前屏幕横竖屏状态

+ (UIInterfaceOrientation)interfaceOrientation {

    if (@available(iOS 13.0, *)) {

        return [UIApplication sharedApplication].windows.firstObject.windowScene.interfaceOrientation;

    }

    return [[UIApplication sharedApplication] statusBarOrientation];

}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

/// 旋转屏幕

/// - Parameters:

///   - interfaceOrientation: 目标屏幕方向

///   - viewController: 所在的视图控制器

///   - errorHandler: 错误回调

+ (void)rotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation viewController:(UIViewController *)viewController errorHandler:(void (^)(NSError *))errorHandler {

#if __IPHONE_16_0 //兼容 Xcode13

    if (@available(iOS 16.0, *)) {

        UIWindowScene *windowScene = viewController.view.window.windowScene;

        if (!windowScene) {

            return;

        }

        [viewController setNeedsUpdateOfSupportedInterfaceOrientations];

        UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] init];

        switch (interfaceOrientation) {

            case UIInterfaceOrientationPortrait:

                geometryPreferences.interfaceOrientations = UIInterfaceOrientationMaskPortrait;

                break;

            case UIInterfaceOrientationPortraitUpsideDown:

                geometryPreferences.interfaceOrientations = UIInterfaceOrientationMaskPortraitUpsideDown;

                break;

            case UIInterfaceOrientationLandscapeLeft:{

                geometryPreferences.interfaceOrientations = UIInterfaceOrientationMaskLandscapeLeft;

                NSLog(@"横屏");

            }

                break;

            case UIInterfaceOrientationLandscapeRight:

                geometryPreferences.interfaceOrientations = UIInterfaceOrientationMaskLandscapeRight;

                break;

            default:

                break;

        }

        [windowScene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) {

            //业务代码

            //NSLog(@"menglc errorHandler error %@", error);

            if (errorHandler) {

                errorHandler(error);

            }

        }];

        return;

    }

#endif

    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 = UIInterfaceOrientationLandscapeRight;//横屏UIInterfaceOrientationPortrait

        [invocation setArgument:&val atIndex:2];

        [invocation invoke];

    }

}

不仅可以在上述方法case更新view位置与大小;还可以在第二项第二个方法中更新view位置与大小 - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator

参与文献:iOS 16横竖屏切换适配_ios16横屏弹出一个竖屏的view-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值