iOS横屏实践 2022-04-15 周五

简介

  • 工程绝大多数界面只支持竖屏(大多数)

  • 其中的拍照界面只支持横屏(少数)

工程配置

  • 理论上,工程配置是其效果的。通常的应用会配置为只支持竖屏。
    屏幕旋转在大多数情况下是个副作用,所以整体配置上需要禁止旋转。
工程配置
  • 问题: 这样设置不起效果!!!
    原因: Info文件中增加了内容,没有改全。
Info.plist

代码配置

  • 工程Plist配置影响了初始化,在代码中可以进行修改覆盖。修改的地方在AppDelegate,只是以代理回调方法的形式存在,设置起来并不方便。

*AppDelegate只有一个,并且系统提供了类似单例的访问方法,这为修改带来了方便。

  • 与工程配置相比,代码配置更加灵活。可以在特定的时候进行修改。

  • AppDelegate.h中提供一个属性供外部设置,修改。

@interface AppDelegate : UIResponder <UIApplicationDelegate>

// 与SceneDelegate中的window是同一个;
// 很多第三方库,比如SVProgressHUD要用到;
// 自己以view的方式做弹窗也要用到;
@property (nonatomic, strong) UIWindow *window;

// NO:只支持竖屏;YES:支持横屏(Home键在右)
@property (nonatomic, assign) BOOL isLandscapeRight;

@end
  • AppDelegate.m中修改配置
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    // 默认不支持横屏,只支持竖屏
    self.isLandscapeRight = NO;
    
    return YES;
}

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    // 大多数情况只支持竖屏,少部分情况只支持横屏(Home键向右)
    if (self.isLandscapeRight) {
        return UIInterfaceOrientationMaskLandscapeRight;
    } else {
        return UIInterfaceOrientationMaskPortrait;
    }
}

旋转手机

  • AppDelegate.m中只是设置了xxxMask,代表了允许手机旋转的方向范围,并没有让手机实际旋转。

  • 旋转手机的APIUIDevice中,可是苹果并没有开发这个API,目前可以通过KVO的方式间接调用。

这真的是很扯淡的事情。
iOS强制改变物理设备方向的进阶方法

// 旋转手机
+ (void)forceToOrientation:(UIDeviceOrientation)orientation {
    NSNumber *orientationTarget = [NSNumber numberWithInteger:orientation];
    [[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
}
  • 实现旋转:要求Mask和实际的旋转动作相配套。不然的话没有效果。

比如,你在AppDelegate.m设置只能竖屏的Mask,但是你却要求横屏向右旋转,结果当然是没效果。(自相矛盾啊)

// 旋转到横屏
+ (void)rotateToLandscapeRight {
    // 先设置Mask
    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    appDelegate.isLandscapeRight = YES;
    
    // 然后旋转手机;方向需要在Mask的范围之内
    [PDADevice forceToOrientation:UIDeviceOrientationLandscapeRight];
}

// 旋转到竖屏
+ (void)rotateToPortrait {
    // 先设置Mask
    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    appDelegate.isLandscapeRight = NO;
    
    // 然后旋转手机;方向需要在Mask的范围之内
    [PDADevice forceToOrientation:UIDeviceOrientationPortrait];
}

调用时机

由于绝大多数页面只需要竖屏就可以了,这个只要在工程配置的地方配置一下就行。
对于需要横屏的页面,可以在viewWillAppear中设置为横屏,然后在viewWillDisappear中设置为竖屏就可以了。

- (void)viewWillAppear:(BOOL)animated {
    /*
     * 设置横屏
     */
    [PDADevice rotateToLandscapeRight];
}

- (void)viewWillDisappear:(BOOL)animated {
    /*
     * 设置竖屏
     */
    [PDADevice rotateToPortrait];
}

参考文章

iOS固定APP 某个界面强制横屏或者竖屏

iOS强制改变物理设备方向的进阶方法

iOS 不勾选设置工程Landscape,实现某个界面强制横屏

iOS设置某个界面强制横屏,进入就横屏

失效的屏幕旋转方法

  • 很多文章都说重写下面几个方法,可以实现屏幕旋转。可是实际试过之后才知道并不可行。
- (BOOL)shouldAutorotate {
    return NO; // 注意:如果是只支持一种,比如只支持横屏,这里需要设置为NO;YES的至少需要两种或者以上的Mask才行。
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeRight;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}
  • 之所以要通过重写getter方法的方式来实现修改的目的,是因为UIViewController的这3个属性是只读的。
// New Autorotation support.
@property(nonatomic, readonly) BOOL shouldAutorotate API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
@property(nonatomic, readonly) UIInterfaceOrientationMask supportedInterfaceOrientations API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
// Returns interface orientation masks.
@property(nonatomic, readonly) UIInterfaceOrientation preferredInterfaceOrientationForPresentation API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(tvos);
  • 如果是present出来的界面,上面的设置是可以起效果的。

  • 如果是Navigation Controller管理,push(show)出来的界面,上面那样设置是不起效果的。因为Navigation Controller是容器,UIViewContainer是容器里的物品。容器和物品的方向要一致才能起效果。
    所以,导致大部分时候,上面这些代码不起作用,估计大概率的原因是两者不匹配导致的。

吐槽

  • 旋转屏幕,固定屏幕朝向,直观上应该是很简单的一个功能,但是实际用下来,却要用到黑科技(KVO)。这不得不让人吐槽苹果真不厚道。

  • 就算是通过属性设置,却提供好几个“只读”属性,并且要好几个属性配合起来才行。

  • 更夸张的是设定当前UIViewContainer的朝向,还竟然要考虑容器Navigation Controller的朝向,还要保证两者一致才有可能起效果。

  • 这样搞,要么就是存心不让人使用改变屏幕朝向的API;要么就是设计这些个API的人是蠢货。苹果工程师出蠢货也不是一两个例子了。

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

推荐阅读更多精彩内容