怎么适配高分屏_iOS 关于全面屏适配的方案及UI在不同尺寸下适配方案

Hsusue Cocoa开发者社区

前言

全面屏刚出时,网上有说反人类。但过去这么久了,趋于技术的进步或看久了,大家也都慢慢习惯了(只是笔者还是买不起全面屏)。官方适配中文版文档也出来了。

bcbb9154950f08e04bf50bbc2d750fbc.png
27d6ac02b56a6e3e7d42a8352df2973f.png

回想起刚开始适配全面屏用了一种暴力、并不优雅的方法,以至于后来出了XS(MAX)和XR后出了bug。所以选择一种可靠的、优雅的方案是很有必要的。如今网上关于探讨适配全面屏的文章五花八门,笔者将探究其中的各种方案。

由于笔者水平有限,眼界狭窄,难免出现疏忽的地方,希望大神提出更好的方案。

全面屏的数据

  • 顶部
111cf4d004c9c803008dd5760f5f8113.png
b37c6fb2225dabd874206eb67868f752.png

从以上两图,我们可以看出全面屏的顶部Statusbar变高了,其他部分没变。

Largetitle是iOS11中新加入的特性。当然我们开发中很少用到Largetitle。

  • 底部

全面屏底部多出了高度为34的Home Indicator 区域。

4dd08a58e3821843c71d1a5e0793936e.png

个人总结的全面屏适配观点

1.虽然笔者买不起XStyle,但是虚拟器应该能满足适配的所有测试。

所以开发中,请优先使用全面屏开发。笔者有个朋友,开发时用非全面屏,偶尔会出现忘记适配全面屏问题。如果用全面屏,开发效率将会进一步提升。毕竟界面适配全面屏的时候,很难忘记适配非全面屏。

2.App显示界面大小是由App启动页决定的。

记得iPhoneX刚出时,App在其上面运行显示居中,大小和6s一样,上下各有一块黑块。尝试打印出分辨率惊奇发现不是官方宣传的1124,2436。把启动页大小改了宏才达到预想效果。如果用xib,那就没什么问题。启动页用图片的话,要适配上@3x的图片。

3.宏怎么定义

宏里只要能区分开XStyle,其他高度就好说。

网上很多教程都是按照分辨率来区分。然而,根据上面我们可以发现,XStyle的分辨率并非固定。所以单纯按照分辨率是不行的。笔者一开始适配X就是这样,后来XSMax出了问题,被迫强行更新XCode10用XSMax,发现宏没写好(顺便吐槽一句,XCode10真是噩梦,又懒得下回去)。

也有旧教程是按照屏幕宽高。但根据上面数据也不是固定的,所以要注意。这两种失效宏都列在下面。

// 单纯根据分辨率#define K_iPhoneXStyle ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)// 单纯根据屏幕宽高#define K_iPhoneXStyle (KScreenWidth == 375.f && KScreenHeight == 812.f ? YES : NO)

其实笔者很想弄出一个通用的宏,不那么怕出新机会失效的宏,但奈何实在想不到。只能照XStyle不一样的数据写出宏。下面列出的宏在XS Max时还是有效的。至于以后就说不准了,各位还是要根据新机分辨率或者宽高适当修改。

#define K_iPhoneXStyle ( (CGSizeEqualToSize(CGSizeMake(414, 896), [[UIScreen mainScreen] bounds].size)) || ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) )

或者

#define K_iPhoneXStyle ((KScreenWidth == 375.f && KScreenHeight == 812.f ? YES : NO) || (KScreenWidth == 414.f && KScreenHeight == 896.f ? YES : NO))

还有其他的宏

#define KScreenWidth ([UIScreen mainScreen].bounds.size.width)#define KScreenHeight ([UIScreen mainScreen].bounds.size.height)#define K_iPhoneXStyle ((KScreenWidth == 375.f && KScreenHeight == 812.f ? YES : NO) || (KScreenWidth == 414.f && KScreenHeight == 896.f ? YES : NO))#define KStatusBarAndNavigationBarHeight (K_iPhoneXStyle ? 88.f : 64.f)#define KStatusBarHeight (K_iPhoneXStyle ? 44.f : 20.f)#define KTabbarHeight (K_iPhoneXStyle ? 83.f : 49.f)#define KMagrinBottom (K_iPhoneXStyle ? 34.f : 0.f)

还有些宏,是适配字体或者view用的。将在后面介绍UI在不同尺寸下适配方案再提起。

#define KScaleWidth(width) ((width)*(KScreenWidth/375.f))#define IsIphone6P SCREEN_WIDTH==414#define SizeScale (IsIphone6P ? 1.5 : 1)#define kFontSize(value) value*SizeScale#define kFont(value) [UIFont systemFontOfSize:value*SizeScale]

最后说一句,利用宏来写虽然简单,但有以下弊端。

  • 找不到能可靠性强的宏XStyle。毕竟以后的手机分辨率或者屏幕宽高肯定会变化(即使短时间内不会)。要适应新机型就要重新上线。
  • 假如以后新出的机刘海长度变了,到时又要修改宏。
  • App适配起横屏,也挺麻烦的。

即使有弊端,笔者还是觉得这么写可行。毕竟大多数App都不用支持横屏,而且屏幕短时间内不会有太大变动。

人要保持一颗活到老学到老的心,这些弊端有方法避免。

iOS11出了安全区域SafeArea这个概念,用得好可以解决以上问题。要点时间适应。

弊端是目前大多App都支持iOS11.0-,这样就要写判断版本号,代码多将近一倍。

优点也很明显

  • 如果苹果新出了新机型,不用改动代码适应的可能性非常大。这意味着不用为了适配问题上线新版本。
  • 横屏时顶部不会有偏移。有横屏需求的话,也许就不用为了横屏做额外适配。

等以后App iOS11.0起步的时候(短时间不太可能qaq),个人感觉SafeArea将会成为主流。

但至少目前,看上去很美好,实际上适配写多一倍的代码让笔者望而生畏。

4.SafeAreaiOS7以后,苹果给UIViewController引入了topLayoutGuide 和 bottomLayoutGuide两个属性。用于表示顶部或底部的高度。根据有无显示状态栏、导航栏、tabBar返回高度。如果VC内嵌VC,内嵌的VC将视为另起的顶底坐标体系,不受原状态栏等影响。你可能听都没听过这两属性,因为开发中我们习惯直接用宏写上数值,几乎不用这两个属性。更何况那时iPhone还没有全面屏这种东西。

到了iOS11,苹果弃用了topLayoutGuide和bottomLayoutGuide两个属性。引入了safeArea代替。官方的建议是 不能被遮挡的内容和控件在安全区域范围内显示。如果视图底部有按钮,在全面屏下,请约束底部距离34,不要影响到Home功能。

  • safeAreaLayoutGuide

此属性适用于自动布局。

32fd2c3356224d86104c9696f73f9125.png

使用前

[NSLayoutConstraint constraintWithItem:someView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];

使用后

[NSLayoutConstraint constraintWithItem:someView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view.safeAreaLayoutGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];

笔者用的是Masonry。注意该属性是iOS11后出现的。因为X发布时,最低版本超过了11,所以全面屏都能用此属性。在这里可以看出,因为11不支持,这代码多了一倍。我们完全可以不用这新属性,减少一半代码爽歪歪。所以笔者目前开发还未使用。

 [testView mas_makeConstraints:^(MASConstraintMaker *make) { make.height.equalTo(@44); if (@available(iOS 11.0,*)) { make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop); make.left.equalTo(self.view.mas_safeAreaLayoutGuideLeft); make.right.equalTo(self.view.mas_safeAreaLayoutGuideRight); } else { make.top.equalTo(self.view).offset(KStatusBarHeight); make.left.equalTo(self.view); make.right.equalTo(self.view); } }];

笔者没有全面屏,只能展示一下热点了。该效果与用宏KStatusBarHeight一样。

(注:此手机系统12.0)

53ccc153f5759154e77a7393693da380.gif

但横屏时就不一样了。宏写法会与上方有一段KStatusBarHeight距离,此方法没有。这就是笔者说的其中一个优点,然而并没有好到足够让笔者用它的程度。

b39374965662096c676ca88367c6ddf9.png

最后有两个观点。

  1. 对于在ViewController的view,推荐使用mas_safeAreaLayoutGuide。这样就能动态更改,即使横屏。
  2. 对于在View之间的约束,推荐使用mas_left。一来没必要用safeArea,二来不用判断版本号,减少代码量。
  • safeAreaInsets

此属性适用于手动计算frame。

X竖屏时控制器view的safeAreaInsets是(44,0,34,0);横屏(0, 44, 21, 44)。

ac9c43632b9e99e41fd7e8b9d9247922.png

用到的是这个方法- (void)viewSafeAreaInsetsDidChange;

- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor redColor]; UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(0, KStatusBarHeight, KScreenWidth, 200)]; testView.backgroundColor = [UIColor blackColor]; [self.view addSubview:testView]; self.testView = testView;}- (void)viewSafeAreaInsetsDidChange { [super viewSafeAreaInsetsDidChange]; NSLog(@"%s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值