iPhoneX适配

1. 屏幕大小

iPhoneX屏幕大小为375x812个点,相比于iPhone6和7的375x667个点 在垂直方向上多出145个点,需要注意的是坐标系的原点为方框的左上角,也就意味着如果代码给控件设置绝对frame有可能会被四周圆角或者顶部的摄像头区域给切掉。
图1坐标系.png

2. 各种高度改变

iPhoneX的状态栏高度由之前的20个点变为44个点(如图2状态栏和导航栏)
图2状态栏和导航栏.png

导航栏的高度默认情况下还是44,iOS11之后新增大标题模式,largeTitle开启的情况导航栏高度是96,除去原有的高度在下面多出了52个点高度的显示大标题的地方。(图3大标题模式)
图3大标题模式.png

tabBar的高度没有变 依旧是49,不过在tabBar下面还有一个高度为34的带圆角的区域,这个区域中包含HomeIndicator提供给用户返回Home和唤出多任务的功能。

3. safeArea

iOS11新增safeArea的概念就是苹果为了给开发者提供一个适配和开发的准则, 安全区域就是能够正常有效的显示视图并和用户交互的区域,区域大小并不是固定的 而是根据控制器否有导航栏、状态栏、tabBar、ToolBar动态改变的。 原则上所有非滚动试图都应该显示在安全区域内以保证正确的显示和交互。竖屏安全区域 (图4竖屏安全区域)
图4竖屏安全区域.png

和横屏下的安全区域 (图5横屏安全区域)
图5横屏安全区域.png

4. 检查自己的应用哪些地方需要适配

Xcode9带有iPhoneX的模拟器,可以在上面运行查看自己应用的显示情况,如果发现自己的app在X下运行时上下都有黑条,那是因为应用在启动的时候没有对应的启动图,所以需要添加在X下运行的@3X的1125X2436px大小的启动图,准备好启动图后showInFinder放到启动图文件夹下,然后在Contents.json中添加对应的描述即可

{
      "extent" : "full-screen",
      "idiom" : "iphone",
      "subtype" : "2436h",
      "filename" : "0b1@2x-1.png",
      "minimum-system-version" : "11.0",
      "orientation" : "portrait",
      "scale" : "3x"
    },

注意filename是你启动图的名字,如果添加后Contents.json的格式不正确,可以新建一个lanchImage,新建的lanchImage文件夹下的Contents.json带有iPhoneX启动图的描述, 然后在新建的lanchImage中找到Contents.json文件中的相关描述复制过来即可。

5. 界面的适配

应用大部分都是竖屏界面,先说说竖屏界面的适配.

  • 对于使用系统的导航控制器和TabBar控制器的话,运行在X上的时候系统会自动把背景拉伸到合适的位置,以适应X的显示。如果是自定义的Navigation或则TabBar可能就需要去适配了。 判断是否是X来让Navigationbar和TabBar显示在合适的位置。

  • 对于纯代码实现的view,因为参照的固定高度在iPhoneX下发生了改变,可能会出现内容显示在安全区域之外的情况。所以要区别iPhoneX与其他设备来动态的改变控件的布局,为此定义了几个宏,因为控制器中的需要适配的view可能不止一个,所以如果一个一个去改frame的话太麻烦,我的思路是先添加一个安全区域大小的contentView,然后让之前所有的控件都加在contentView上,这样会减少部分代码修改,并且如果之后再修改的会简单点。

#define  ScreenWidth   [UIScreen mainScreen].bounds.size.width
#define  ScreenHeight  [UIScreen mainScreen].bounds.size.height
#define  iPhoneX (ScreenWidth == 375.f && ScreenHeight == 812.f ? YES : NO)
#define  StatusBarHeight      (iPhoneX ? 44.f : 20.f)
#define  NavigationBarHeight  44.f
#define  TabbarHeight         (iPhoneX ? (49.f+34.f) : 49.f)
#define  TabbarSafeBottomMargin         (iPhoneX ? 34.f : 0.f)

#define  LanscapeLeftMargin         (iPhoneX ? 44.f : 0.f)
#define  LanscapeRightMargin         (iPhoneX ? 44.f : 0.f)
#define  LanscapeBottomMargin         (iPhoneX ? 0.f : 0.f)

  • xib的适配,如果项目的最低部署版本是9.0以上,可以直接在xib文件的描述设置中勾选使用安全区域布局(如图6xib打开safeArea)这样文件会自动添加一个安全区域,然后在需要适配的地方(比如上下左右)改为约束参照safeArea即可 系统会自动调整显示内容。如果最低部署版本是9.0以下,不能使用safeArea, 勾选之后编译报错,这时只能自己去调整了。 我自己适配的思路还是添加一个contentView,给contentView添加约束大小为安全区域的大小, 把所有控件都添加到contentView上面重新设置约束保持原来的布局, 然后在代码中根据机型动态调整contentView的约束。
    图6xib打开safeArea.png

6. 导航栏的适配

在iOS11下导航栏左边和右边item的位置发生了变化,左边的往右移动了一段距离,而右边的往左移动了一段距离,好像是20个点。而在iOS11之前内边距也是存在的,但是大部分都是加了一个负距离的FixedSpace的适配好了。但是在iOS11中 导航栏的结构发生了变化,(如图7导航栏结构)在iOS11下就会出现偏移距离的问题。怎么解决呢?
图7导航栏结构.png
  1. 给leftButton设置x值为-20 ? 测试后发现ButtonBarStackView的大小和button的大小一样,但是位置没有变化。并且即使这样button的位置起作用了,超出父控件的部分不能接收事件。

  2. 能不能在控制器的view显示之前遍历navigationbar的子控件拿到UIButtonBarStackView,然后改变其约束呢? 我把遍历的代码写在viewWillAppear中 发现遍历后打印的数组是空的,放在didAppear中遍历就有了,但是这样不行 因为在DidAppear中重新设置UIButtonBarStackView的位置的话,控制器显示后可以看到button的移动 🤣

  3. 可以设置button的内容偏移contentEdgeInsets 让按钮的内容往左或者往右偏移20 的距离,但是会出现用户点击返回按钮但是没有反应的情况。可以重写navigationBar 的hitTest方法 判断点击的位置如果是左边的button就让左边的button接受事件,右边的同理。怎样重写UINavigationBar的方法呢 一种是继承然后重写,但是这种明显不适合系统控件,第二种就是给UINavigationBar添加分类 然后在分类中重写hitTest方法 然后判断点击的位置是左边的还是右边的,返回对应的button即可

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
   UIView *view = [super hitTest:point withEvent:event];
   if (point.x < [UIScreen mainScreen].bounds.size.width * 0.5) {

       for (UIBarButtonItem *item in self.topItem.leftBarButtonItems) {
           if (item.customView == nil) {
               continue;
           }
           if ([item.customView isKindOfClass:[HitButton class]]) {
               HitButton *leftButton = (HitButton *)item.customView;
               CGRect newRect = [leftButton convertRect:leftButton.hitFrame toView:self];
               if (CGRectContainsPoint(newRect, point)) {
                   view = leftButton;
                   break;
               }
           }
       }
   }else{
       for (UIBarButtonItem *item in self.topItem.rightBarButtonItems) {
           if (item.customView == nil) {
               continue;
           }
           if ([item.customView isKindOfClass:[HitButton class]]) {
               HitButton *rightButton = (HitButton *)item.customView;
               CGRect newRect = [rightButton convertRect:rightButton.hitFrame toView:self];
               if (CGRectContainsPoint(newRect, point)) {
                   view = rightButton;
                   break;
               }
           }
       }
   }
   return view;
}

7. tableView的适配

  • 在iOS11之后,UIViewController的automaticallyAdjustsScrollViewInsets属性被废弃,取而代之的是给UIScrollView添加了contentInsetAdjustmentBehavior属性 该属性枚举类型,控制器当scrollView靠近状态栏或者导航栏时content调整的策略, 默认是自动调整,这样如果scrollView出现在状态栏或者导航栏下面 在iOS11下面会自动调整内容向下偏移,如果不想偏移的话可以设置contentInsetAdjustmentBehavior的属性为never即可
  • 下面的一堆属性默认都是自适应了 所以如果发现tableView显示出现异常,设置对应的属性为0或者在代理方法中返回0即可
@property (nonatomic) CGFloat rowHeight;             // default is UITableViewAutomaticDimension
@property (nonatomic) CGFloat sectionHeaderHeight;   // default is UITableViewAutomaticDimension
@property (nonatomic) CGFloat sectionFooterHeight;   // default is UITableViewAutomaticDimension
@property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
@property (nonatomic) CGFloat estimatedSectionHeaderHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
@property (nonatomic) CGFloat estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable

  • 横屏下tabView会自动调整其contentView的位置以显示在安全区域中,所以如果是纯代码自定义的cell,务必保证添加子控件到contentView上
  • 对于像tableVie和collectionView这样的流式布局在底部的约束苹果建议是到屏幕底部,不应约束在safeArea中 系统中的应用也是这样做的 像设置界面 homeIndicator就是在tableViewCell的上面,但是不影响tableView的交互,点击的话可以正常响应事件,并且上划的回到home

8. 视频横屏播放适配

  • homeIndicator的隐藏
    原则上不要隐藏homeIndicator 并且不要在其附近摆放控件 设置交互 以免和系统的交互冲突。特殊状态下需要隐藏homeIndicator , 比如视频横屏播放 或者播放ppt等需要全屏显示的时候。和状态栏的隐藏类似 ,在控制器中 实现方法 - (bool)prefersHomeIndicatorAutoHidden 但是和隐藏状态栏不同是 即使该方法返回的是YES ,homeIndicator也不会立即隐藏 而是交给系统去判断,当系统认为时机合适时给与隐藏(比如控制器一段时间内没有事件交互)不合适的时候(有事件交互) 还是会显示出来

  • 播放画面填充
    因为iPhoneX屏幕比例不同于以往的16:9, 画面不能按照正常比例充满屏幕, 视频横屏播放的时候有两种填充方案,一种是AspectFit ,这种画面按比例显示完整,但是会有部分屏幕没有显示画面。另外一中方式AspectFill, 按比例充满,但是会切割部分画面,苹果鼓励应用把两个选项提供给用户,让用户选择画面的填充模式。


    图8aspectToFit.png
    图9aspectToFill.png
  • 边缘手势冲突
    注意如果你的应用在下边缘有手势触发的交互一定要和homeIndicator区别开,如果一定要在下边缘添加手势的话可以开启EdgeProtection 开启边缘保护后 第一次轻扫会唤醒homeIndicator并且激活控件,当第二次轻扫的时候才会唤醒多任务界面。但是苹果建议不是特殊情况不要这样使用,因为会影响用户体验
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容

  • 苹果公司于9月份如期发布了新的iPhone-iPhone8,iPhone8 Plus,iPhoneX,前两个不用多...
    MonkeyHeng阅读 8,665评论 5 43
  • 前言 苹果WWDC开发者大会上,终于发布了大家期待已久的iOS 11,有些新特性功能确实出人意料。不过大的方面苹果...
    Mr_Say_Yes阅读 3,305评论 6 15
  • 随着Xcode GM版本发布,适配iOS 11也就提上了日程,总的来说整个适配过程不是很麻烦。建议观看今年WWDC...
    iOS骆驼阅读 2,690评论 1 6
  • https://developer.apple.com/ios/human-interface-guideline...
    iOS白水阅读 782评论 0 8
  • 2017.6.15 周四 天晴晴朗 心情愉悦 今日很充实,早上起来开始健身阅读,自己做早餐,沟通意向代理,还...
    李凡520阅读 230评论 0 0