ios开发横竖屏切换方案,横屏方法不起作用,失效原因。

最近接手了一个老项目,还是oc写的。可能经过了很多手,其中的屏幕旋转方法写了很多种。有些假横屏,有些强制横屏,有些真横屏。有些地方需要横屏却横不过来。有些却横屏后恢复竖屏导致布局错乱。复习了一下oc横屏方法,准备全部重新写一下。

关于ios开发中,控制界面的展示方向(通俗来说就是横屏竖屏)。我们发现有很多相关的属性设置,目前比较常见的是5个地方。分别是

  1. Target → General → Deployment Info → iPhone Orientation。写displayname那边的勾选框,也就是info.plist中声明的屏幕方向。

2.AppDelegate:- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window 运行时方法

3.- (BOOL)shouldAutorotate。

4.- (UIInterfaceOrientationMask)supportedInterfaceOrientations

5.- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation

这5个属性有些相互影响,有些设置了不起作用,不了解的话可能会比较迷惑。

下面我打算比较简单粗暴的说一下他们之间的关系,和最最简单的控制屏幕的方法。

第一个:
Target → General → Deployment Info → iPhone Orientation。

image.png

这里的配置,并不是硬性限制。可以理解为初始化设置,当你其他什么都没设置时,应用进来的方向,就以它为准。

第二:

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
     return UIInterfaceOrientationMaskAllButUpsideDown;
}

这个方法才是真正决定屏幕最终方向的方法,可以覆盖方法1的设置。(原因:对于UIApplicationDelegate的这个方法声明,大多数情况下application就是当前的application,而window通常也只有一个。所以这个方法对横屏竖屏interfaceOrientation的控制相当于全局的。)
如果这里面你设置了
return UIInterfaceOrientationMaskPortrait;
那无论你其他怎么设置,就永远是竖屏。

所以我们讨论的是 这个方法中 你返回的是多种方向,例如:
return UIInterfaceOrientationMaskAllButUpsideDown;

那么,它现在允许你的界面根据设备的方向更换界面方向了。那如何才能让有些页面可以横屏,有些页面不可以横屏呢?
接下来,就要提到上述第三个方法ViewController.shouldAutorotate。

第三:

- (BOOL)shouldAutorotate {
       return YES;
  }

(这个方法不写的话,默认为是return yes)

这是一个可以在子类重写的方法,
当你return yes:就相当于打开了旋转开关,当方法二中返回UIInterfaceOrientationMaskAllButUpsideDown。 你的页面就会根据设备的方向而改变为横屏或竖屏。
当你return NO:就相当于关闭了旋转开关。页面永远保持为,刚进入这个页面时候的方向。

然后是第四个方法:

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

这个方法原意是控制某个子页面的可旋转方向的范围,页面初始化的时候会调用。但是你会发现- (UIInterfaceOrientationMask)supportedInterfaceOrientations常常不起作用。
原因:这个代码需要放在决定了视图方向的controller中,比如rootviewcontroller中。或者当前导航控制器的第一个present出来的viewcontroller中。然后其旋转方向又回被方法二覆盖。所以才导致常常不起作用的错觉。(其实确实没啥用)

最后就是第五个方法

 - (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation{
    return self.topViewController.preferredInterfaceOrientationForPresentation;
}

这个方法是一个回调方法,决定了viewController出现时的视图方向,该回调方法只对present方式进入界面的viewController有效果。一般用在present vc的时候模态弹出。来确定页面方向。用的不多。

然后总结就是项目中控制页面横屏的方案。举例:一个项目,大多数页面都是竖屏,偶尔几个如视频播放页,手写签名页面等等需要横屏。

1.target → General → Deployment Info → iPhone Orientation 仅仅勾选Portrait。

2.项目中写一个父类BaseviewController,在里面写

- (BOOL)shouldAutorotate {
 return NO;
}

其他页面继承BaseviewController。 需要横屏的页面重写

- (BOOL)shouldAutorotate { 
return YES;
}

3.在AppDelegate中

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
 return UIInterfaceOrientationMaskAllButUpsideDown;
}

应该就可以了。

最后在说一下强制横屏和假横屏。
强制横屏:设备其实我没有横着拿,但是我让界面横屏,典型例子就是 播放器全屏按钮。

NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];

假横屏:就是其实ViewController没有横屏,只是把界面里面的Views 就是subview们给旋转了。
/// 根据当前 view 的宽高,做「内部伪横屏」的布局与旋转

- (void)layoutPseudoLandscapeAnimated:(BOOL)animated {
    CGFloat screenW = self.view.bounds.size.width;
    CGFloat screenH = self.view.bounds.size.height;

    // 无论外部实际方向如何,内部一律按「横屏」尺寸来排版:
    // viewW = 长边,viewH = 短边
    CGFloat viewW = MAX(screenW, screenH);
    CGFloat viewH = MIN(screenW, screenH);

    // 先把 baseView 的 bounds 设置成横屏的尺寸,再居中
    self.baseView.bounds = (CGRect){ CGPointZero, CGSizeMake(viewW, viewH) };
    self.baseView.center = CGPointMake(screenW * 0.5, screenH * 0.5);

    // 签名区域铺满 baseView;签名内部的工具栏、关闭按钮等由 XTQMSignatureView 自己 layout
    self.signView.frame = self.baseView.bounds;

    // 外部是竖屏(H > W)时,需要把 baseView 旋转 90°;外部横屏则不旋转
    CGAffineTransform target = (screenH > screenW) ? CGAffineTransformMakeRotation(M_PI_2) : CGAffineTransformIdentity;

    if (animated) {
        [UIView animateWithDuration:0.25
                         animations:^{
                             self.baseView.transform = target;
                         }];
    } else {
        self.baseView.transform = target;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容