iOS竖屏App强制某一部分横屏

前言

很长时间没有更新简书,原因不多说(因为懒),最近比较清闲,想起来写一篇文章来说一下iOS横竖屏轻松切换的过程。 有些需求整体的App只支持竖屏,但是只需要某一部分页面支持横屏,许多的视频类的App都要在竖屏的情况下进行横屏播放,当然还有很多的奇葩需求要横屏来进行实现。

废话少说,进主题

创建项目,App的方向只需要勾选Portrait就行(其实可以不用勾,但是能有几个项目中不勾的呢,我们还是勾上吧)。

勾选方向

前面说可以不勾选因为我们要在AppDelegate中,重写这个方法, 应用程序启动的时候会调用这个方法来给App所需要的屏幕方向:

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    if([ScreenDirectionManager manager].islandscape) {
        return UIInterfaceOrientationMaskLandscape;
    }else {
        return UIInterfaceOrientationMaskAll;
    }
    
}

其中UIInterfaceOrientationMask是一个NS_OPTIONS, 我们可以随意组合,虽然其中有一些组合好的,但是万一不满足产品的奇葩需求呢,对不对,要提前留一手。

typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
    UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
    UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
    UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
    UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
    UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
    UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
    UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
} __TVOS_PROHIBITED;

意思内容不用多解释,应该都能知道什么意思。

其中ScreenDirectionManager这个类控制屏幕是否横屏,是一个单例就一个属性是否需要横屏,比较简单。

@interface ScreenDirectionManager : NSObject

+ (instancetype)manager;

@property (nonatomic, assign, getter=islandscape) BOOL landscape;

@end

如果你的App不包括导航栏(UINaviagtionController)或者(UITabbarController),你只需要重写UIViewController里面的三个方法就行,这三个方法是:

//  返回bool值,决定Controller是否自动旋转
-(BOOL)shouldAutorotate
//返回一个Controller支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
//返回现在正在显示的用户界面方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation

但是一般的应用至少有个导航栏吧,所以呢你还需要自定义导航栏(UINavigationController),然后在导航栏里面重写这三个方法,如果不重写,就无法达到你想要的效果,感觉就像这个屏幕方向具有传递的性质。但是我感觉UITabbarController的情况应该少数,我这里不讨论这个情况,下次有空再补上,但是我感觉原理应该是一样的,有兴趣的可以自己试一下。

导航栏的屏幕方向和旋转性质要和导航栏最上层的Controller保持一致,所以自定义导航栏重写的三个方法是这样的:

-(BOOL)shouldAutorotate {
    return [[self.viewControllers lastObject] shouldAutorotate];
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

ViewController中,重写上述的三个方法,返回自己想要的方向,那个改Controller只能是返回的方向,例如:

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

- (BOOL)shouldAutorotate {
    return YES;
}

在第二个页面中,也就是跳转的页面中,重写上述的三个方法,返回自己想要的方向,然后在viewWillAppear方法中设定将单例的属性方向改变,然后根据UIDeviceorientation这个属性,根据KVC,强制设置方向,如下;

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [ScreenDirectionManager manager].landscape = YES;
    if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
//写这句话的目的是保证后面的一句话产生作用,具体不明白为什么,但是不加上会出现bug。有明白的可以告知一下。
        [[UIDevice currentDevice] setValue:@(UIDeviceOrientationUnknown) forKey:@"orientation"];
        [[UIDevice currentDevice] setValue:@(UIDeviceOrientationLandscapeLeft) forKey:@"orientation"];
    }
    
}

还需要在viewWillDisappear中,将单例的横竖屏属性改变回来,因为supportedInterfaceOrientations这个方法会触发AppDelegate中的方向支持方法。

结论

文章描述的不太清楚的,欢迎留言讨论。Demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • 很多时候,项目中都有这样的需求:APP中以竖屏为主,个别界面会要求横屏显示,或者要根据用户的手机朝向自动切换横竖屏...
    流火绯瞳阅读 22,134评论 50 62
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,364评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,010评论 4 62
  • 经过十年的工作经历,随着面临的工作越来越难,接触的面越来越广,接触的人越来越多,越发觉得自己的知识匮乏,难以胜任现...
    0ac91607e589阅读 217评论 0 0
  • #羡慕别人的光环# 是的,光环很显眼,容易吸引注意,所以,我们很快看到了别人的光环,然后,心生羡慕之情,然后就没然...
    Ningers阅读 149评论 0 0