iOS开发中屏幕旋转(二)
Morris_ 2019.04.11
前面有总结过一些在开发中遇到的屏幕旋转的基础知识。
一、设置应用支持的转屏方向
设置方式
00x1
在TARGET->General->Deployment Info->Device Orientations下,可设置App支持的屏幕旋转方向。
这里的设置会同步到应用的plist文件中。
00x2
苹果也提供了代码设置app支持的转屏方式的Api:
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {return UIInterfaceOrientationMaskAllButUpsideDown;
}
这个Api是UIApplicationDelegate中的一个方法,我们在AppDelegate.m中实现此协议方法即可。
区别比较
按照00x1设置后,如果代码中又使用了00x2,则00x2会覆盖00x1的设置。但是对于闪屏的方向设置,00x2的方式是无效的,00x1的设置方式确是有效的。可以理解为,应用在进入时,先读取了plist文件中的屏转设置,然后按照plist文件中的设置进行闪屏的展示,程序执行进AppDelegate.m中时,通过00x2中的Api又获取了一次应用所支持的屏转设置,所以闪屏支持的屏幕旋转设置,必须用00x1的方式设置,00x2的设置是无效的,进入应用后应用支持的转屏方式两种方式都可以。
小结
设置闪屏支持的转屏方式,只能使用00x1的方式,00x2的方式是无效的。
如果不使用代码,直接使用00x1的方式,是可行的。
如果既使用00x1的方式,也使用了代码设置,则00x1的方式设置了闪屏支持的旋转方向,00x2的方式设置了进入应用后界面支持的旋转方向。当然个别界面可以单独设置其支持的旋转方向。
二、设置某个界面支持的转屏方向
有必要了解一下苹果提供的UIViewController的分类UIViewControllerRotation。
// To make it more convenient for applications to adopt rotation, a view controller may implement the below methods. Your UIWindow's frame should use [UIScreen mainScreen].bounds as its frame.
@interface UIViewController (UIViewControllerRotation)...略- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
- (UIInterfaceOrientationMask)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
// Returns interface orientation masks.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;...略@end
需要注意一下我们经常用到的设置某个controller支持的屏转方向的三个方法。
- (BOOL)shouldAutorotate
{return YES;//设置当前controller是否支持重力感应,即是否可以转屏
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{return UIInterfaceOrientationMaskAllButUpsideDown;//设置支持的转屏方向
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{return UIInterfaceOrientationPortrait;//设置初始的屏幕方向
}
在iOS开关中屏幕旋转(一)中,有说道present出来的视图和push出来的视图的转屏设置有些区别的,在这里重新说明一下,实际上在本质上是没有什么区别的。
push出来的视图的转屏方式,不是看push出来的controller里的设置,而是由controller所在的navigationController所决定的,navigationController是继承自UIViewController的。本质上,不管push出来多少个视图控制器,显示还是在navigationController下的,所以push出来的视图控制器的转屏方式取决于他的navigationController。
navigationController下的子控制器的转屏方向设置不取决于自己,取决于当前所在的navigationController,因为navigationController是继承于UIViewController的,所以在navigationController里进行转屏设置也是有效的。
为了方便不同界面的转屏设置,我们可以在BaseViewController中添加一个属性orientation,系统的UIViewController有一个属性interfaceOrientation,但是是只读的,不能设置。
@property(nonatomic,readonly) UIInterfaceOrientation interfaceOrientation NS_DEPRECATED_IOS(2_0,8_0) __TVOS_PROHIBITED;
我们可以复写这个属性或者重新写一个UIInterfaceOrientation类型的属性。
@interface BaseViewController : UIViewController@property (nonatomic) UIInterfaceOrientation interfaceOrientation;@end
设置初始默认值,并设置默认不支持转屏,在需要支持转屏的界面单独设置,也可以添加一个是否支持转屏的BOOL类型的属性。
@implementation BaseViewController- (instancetype)init {if (self = [super init]) {_interfaceOrientation = UIInterfaceOrientationPortrait;}return self;
}- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {_interfaceOrientation = UIInterfaceOrientationPortrait;}return self;
}- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.}- (BOOL)shouldAutorotate {return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {return UIInterfaceOrientationMaskAllButUpsideDown;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {return _interfaceOrientation;
}@end
那么有个问题,有navigationController下的控制器,这样设置是无效的,因为navi下的控制器的转屏取决于当前的nav,而不是子控制器。如果在navigationController下有A和B两个controller,A不支持旋转,B需要支持旋转,这怎么处理?在进入A页面的时候设置navi的转屏方式为不可旋转,进入B页面的时候设置为可旋转,原则上这样可以解决这个需求。那么是不是也要给navi写一个类似的属性呢,给navi也写一个这样的属性来控制问题能解决,但是这样就很麻烦。
有没有什么更简单使用的方法呢?
给UIViewController扩展一个设置屏幕旋转方向的属性orientation和一个是否支持屏幕旋转的属性, 注意尽量不要和系统的属性重名,以免覆盖系统提供的功能。
@interface UIViewController (Rotation)//是否支持重力感应 注意不要和系统的shouldAutorotate属性重名,以免覆盖系统提供的功能
@property (nonatomic) BOOL autoRotate;//方向 注意尽量不要和系统的interfaceOrientation属性重名,以免覆盖系统提供的功能
@property (nonatomic) UIInterfaceOrientation orientation;@end
#import "UIViewController+Rotation.h"
#import <objc/runtime.h>static NSString const *kUIViewControllerRotationKey = @"UIViewControllerRotationKey";
static NSString const *kUIViewControllerAutoRotateKey = @"UIViewControllerAutoRotateKey";//为了和系统的分类UIViewController (UIViewControllerRotation)冲突,分类命名为Rotation
@implementation UIViewController (Rotation)- (void)setOrientation:(UIInterfaceOrientation)orientation {NSNumber *number = [NSNumber numberWithInteger:orientation];objc_setAssociatedObject(self, &kUIViewControllerRotationKey, number, OBJC_ASSOCIATION_RETAIN);//注意这里不能用OBJC_ASSOCIATION_ASSIGN
}
- (UIInterfaceOrientation)orientation {NSNumber *number = objc_getAssociatedObject(self, &kUIViewControllerRotationKey);if (number) {return [number integerValue];}return UIInterfaceOrientationUnknown;
}- (void)setAutoRotate:(BOOL)autoRotate {NSNumber *number = [NSNumber numberWithBool:autoRotate];objc_setAssociatedObject(self, &kUIViewControllerAutoRotateKey, number, OBJC_ASSOCIATION_RETAIN);
}
- (BOOL)autoRotate {NSNumber *number = objc_getAssociatedObject(self, &kUIViewControllerAutoRotateKey);if (number) {return [number boolValue];}return YES;
}@end
这样就可以随心所欲的使用这两个属性进行对屏幕旋转的设置了。
- (BOOL)shouldAutorotate {return self.autoRotate;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {return self.orientation;
}
二、关于强制转屏的补充
在iOS开关中屏幕旋转(一)中国有提到过强转屏。
需要注意的是,只有在支持重力感应的情况下才能使用强制转屏方法,否则是转不了的。有些应用是不支持重力感应,但是支持某些界面用户手动去切换全屏。这种需求就需要我们在强制转屏前将autoRotate属性设置为YES,并同时需要实现支持重力感应的方法,手动切换全屏才会有效,或者使用其他的全屏方法。
- (void)rotateScreen:(UIInterfaceOrientation)orientation
{//转屏时,先设置支持重力感应,否则此方法无效self.navigationController.autoRotate = YES;if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]){NSNumber *num = [[NSNumber alloc] initWithInt:orientation];[[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:(id)num];[UIViewController attemptRotationToDeviceOrientation];}SEL selector=NSSelectorFromString(@"setOrientation:");NSInvocation *invocation =[NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];[invocation setSelector:selector];[invocation setTarget:[UIDevice currentDevice]];int val = orientation;[invocation setArgument:&val atIndex:2];[invocation invoke];self.navigationController.autoRotate = NO;self.navigationController.orientation = orientation;
}
-(BOOL)shouldAutorotate
{return self.autoRotate;
}
如上设置,不支持重力感应,但是支持用户手动切换屏幕旋转,只支持手动全屏的需求时,这样处理。
Demo
iOS开发中屏幕旋转(一)
iOS开发中屏幕旋转(二)
iOS开发中屏幕旋转(二)相关推荐
- iOS开发中屏幕旋转(一)
Morris_ 2018.11.24 前言 最近做一个关于在线视频互动的iPad项目,部分界面只要横屏,部分界面可以横竖屏转换.看了看别家做的项目,有些是只做竖/横屏,有些是支持了横竖屏转换,在iPa ...
- IOS(iphone,ipad,itouch)开发 之 屏幕旋转
关于IOS开发中屏幕旋转的问题. 看过很多大牛的文章,都写过类似的,这里我只写一下常用的几个函数的具体用法. 首先是 - (BOOL)shouldAutorotateToInterfaceOrient ...
- iOS开发中经常用的实用代码合集
iOS开发中经常用的实用代码合集 本文整理了,在iOS开发中我们所遇到一些开发问题的技巧类的代码,让你在开发过程中避免了很多弯路,希望能给你的开发带来帮助和启发. 1.判断邮箱格式是否正确的代码: / ...
- (翻译)开始iOS 7中自动布局教程(二)
(翻译)开始iOS 7中自动布局教程(二) 这篇教程的前半部分被翻译出来很久了,我也是通过这个教程学会的IOS自动布局.但是后半部分(即本篇)一直未有翻译,正好最近跳坑翻译,就寻来这篇教程,进行 ...
- iOS开发中常用的方法
iOS开发中常用的方法 系统弹窗: 过期方法: UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"确认报价" ...
- iOS 开发中的 Flux 架构模式
本文讲的是iOS 开发中的 Flux 架构模式, 在半年前,我开始在 PlanGrid iOS 应用程序中采用 Flux 架构(开发).这篇文章将会讨论我们从传统的 MVC 转换到Flux的动机,同时 ...
- iOS开发中一些有用的小代码
1.判断邮箱格式是否正确的代码: //利用正则表达式验证 -(BOOL)isValidateEmail:(NSString *)email { NSString *emailRegex = @&quo ...
- iOS开发中的神兵利器 [实战系列]-李发展-专题视频课程
iOS开发中的神兵利器 [实战系列]-11758人已学习 课程介绍 - 140节课程讲解GitHub中近百个过千star的iOS热门开源项目 - 市面上唯一大规模讲解热门的iOS开源项 ...
- iOS开发中遇到的一些问题及解决方案【转载】
iOS开发中遇到的一些问题及解决方案[转载] 2015-12-29 [385][scrollView不接受点击事件,是因为事件传递失败] // // MyScrollView.m // Creat ...
最新文章
- oracle游标理解,oracle游标的使用方法
- 文巾解题 595. 大的国家
- VTK:平面源用法实战
- Java 8 CompletableFuture
- 第三次学JAVA再学不好就吃翔(part85)--静态导入
- en结尾的单词_以en结尾的英语单词
- axios发送post数据后台收不到_使用axios post 提交数据,后台获取不到
- 1.10 编程基础之简单排序 03 成绩排序 3分 python
- A股股票交易如何计算
- 脱壳--00.aspack.exe
- SpringUtil 工具类
- 如何在iPhone和iPad上的Safari中在网页上查找文本
- mysql57配置教程
- c 语言让电脑自动关机,C语言编写简单的定时关机程序
- 数据库基础_关系与关系模式
- 成都盛铭轩:怎么打造产品差异化
- Maven — maven filtering OTS parsing error incorrect file size in WOFF head 产生原因及两种解决方案
- maven详解2020
- 测回角值计算用计算机,用测回法观测水平角,若半测回角值计算时右目标读数小于左目标读数,则应()。...
- 完美解决win10不认移动硬盘和U盘的问题
热门文章
- Cadence: 各软件业务
- 《商君列传第八》–读书总结
- 【Android 进程保活】应用进程拉活 ( 应用进程拉活简介 | 广播拉活 | 显示广播与隐式广播 | 全家桶拉活 )
- python中abs和fabs的区别_Python - abs vs fabs
- Java实现 LeetCode 93 复原IP地址
- 第六章 姜小白当机立断逃莒国 姜诸儿瓜期不代终遇鬼
- 如何看待用户反馈意见
- guzzle/guzzle 日常使用
- Git问题Everything up-to-date正确解决方法
- 使用开源人脸特征提取器进行脸部颜值评分