背景
今天做地址列表页面, 如图:
tableView 的约束我是这样写的:
[self.tableView mas_makeConstraints: ^(MASConstraintMaker * make) {
make.top.mas_equalTo(myAddressLabel.mas_bottom);
make.left.right.bottom.mas_offset(0);
}];
tableView 滚动的时候是这种效果:
效果. gif
但是当 tableView 滚动到最底部的时候, 最后一个 cell 被挡住了:
home_indicator 挡住了 cell 的内容
于是我针对 iOS 11 调整了一下约束:
[self.tableView mas_makeConstraints: ^(MASConstraintMaker * make) {
make.top.mas_equalTo(myAddressLabel.mas_bottom);
make.left.right.mas_offset(0);
if (@available(iOS 11.0, *)) {
make.bottom.mas_equalTo(self.view.mas_safeAreaLayoutGuideBottom);
} else {
make.bottom.mas_equalTo(self.view);
}
}];
OK, 现在就不会挡住最后一个 cell 了:
home_indicator 不会挡住 cell 的内容
但是滚动 tableView 的时候又尴尬了:
尴尬. gif
对比这张 GIF 与上一张 GIF, 可以发现这里根本没有体现 iPhone X 全面屏的优势.
真正的适配 iPhone X, 是滚动的时候全屏滚动 (如第一张 GIF), 滚到底的时候最后一个 cell 也不会被 home_indicator 挡住.
写了个 demo 研究
为了方便弄清问题我新建了一个小 demo,demo 里我并没有对约束做什么特殊处理:
UITableView *tableView = [[UITableView alloc] init];
[self.view addSubview:tableView];
tableView.dataSource = self;
tableView.delegate = self;
[tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_offset(NAVIGATION_BAR_HEIGHT);
make.left.right.bottom.mas_offset(0);
}];
demo 的效果:
demo.gif
这才是我想要的效果啊!
我很疑惑, 同样的约束代码我用在项目里怎么就不对了.
当初为了适配 iOS 11, 你做了什么?
后来我把这个问题发到群里, 我同学问我是不是用了
automaticallyAdjustsScrollViewInsets
.
这个属性我有用到, 但是 iOS 11 出来后我就没用了, 我用了另一个:
contentInsetAdjustmentBehavior
iOS 11 刚出来的时候, 我发现项目中的 scrollView(及其子类) 在 iOS 11 虚拟机上的偏移量发生了变化, 那个时候关于适配 iOS 11 的文章很多, 我也很轻松的找到了解决方案:
在 AppDelegate.m 中加上这段代码:
if (@available(iOS 11, *)) {
[UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
scrollView 在 iOS 11 上的偏移问题就解决了, 这段代码是什么意思我并未研究, 只是从其字面意思上感觉它就是让 scrollView 不要发生偏移, 但是我并没意识到它跟安全区域有关.
绕不过的安全区域
关于安全区域的文章有很多了, 相信大家就算没仔细研究过, 零散的文章也读了不少, 这里给大家推荐一篇:
https://www.jianshu.com/p/63c0b6cc66fd
现在来说下
[UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever
和安全区域的关系.
appearance:
To customize the appearance of all instances of a class, send the relevant appearance modification messages to the appearance proxy for the class. For example, to modify the bar tint color for all UINavigationBar instances:
[[UINavigationBar appearance] setBarTintColor:myColor];
自己翻译: 自定义所有这个类的对象的外观, 比如说修改所有导航栏的 bar tint color:
[[UINavigationBar appearance] setBarTintColor:myColor];
contentInsetAdjustmentBehavior
:
自己翻译: 是否根据安全区域调整偏移量, 默认是自动调整的.
[UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever
这句话的意思就是所有 scrollView 的偏移量不随安全区域而调整.
这就是项目里的 scrollView 翻到底的时候最后一个 cell 会被 home_indicator 挡住的原因.
又因为
contentInsetAdjustmentBehavior
的默认值是
UIScrollViewContentInsetAdjustmentAutomatic
, 所以小 demo 里 tableView 自动调整了偏移量, 因此翻到底的时候最后一个 cell 不会被 home_indicator 挡住.
所以要解决项目里的 tableView 的显示问题, 只需要将这个 tableView 的
contentInsetAdjustmentBehavior
改为
UIScrollViewContentInsetAdjustmentAutomatic
:
if (@available(iOS 11.0, *)) {
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic;
}
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(myAddressLabel.mas_bottom);
make.left.right.bottom.mas_offset(0);
}];
修改后. gif
反思
最初适配 iPhone X 的时候, 我的想法很简单:
iPhone X 嘛, 无非就是状态栏和 tabbar 的高度发生了变化, 多了一个 home_indicator 而已, 几个宏就搞定了:
// 判断是否是 iPhone X
#define iPhoneX([UIScreen instancesRespondToSelector: @selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO)
// 状态栏高度
#define STATUS_BAR_HEIGHT(iPhoneX ? 44.f: 20.f)
// 导航栏高度
#define NAVIGATION_BAR_HEIGHT(iPhoneX ? 88.f: 64.f)
// tabBar 高度
#define TAB_BAR_HEIGHT(iPhoneX ? (49.f + 34.f) : 49.f)
// home indicator 高度
#define HOME_INDICATOR_HEIGHT(iPhoneX ? 34.f: 0.f)
凭借这几个宏, 我把导航栏和 tabbar 高度一改, 然后就想当然的认为完成了 iPhone X 的适配工作 -- 在别人还在研究安全区域的时候.
当然, tableView 是这样的:
不是全面的全面屏. gif
我想的是: home_indicator 没有挡住 cell 内容就是适配完成了.(还好 APP 的几个主页都是有 tabbar 的, 不存在这种问题, 不然真的丑爆了.)
安全区域是什么? 我知道有这个东西, 这东西重要吗? 反正也不用 (我都用宏解决了), 懒得去管.
事实说明人终将为自己的无知付出代价.
诚如 CepheusSun 所说:
在适配 iPhone X 的时候首先是要理解 safe area 是怎么回事, 盲目的 if iPhoneX{} 只会给之后的工作带来更多的麻烦.
最后, 再次强调
真正的适配效果是:
正确姿势. gif
不是:
home_indicator 挡住了最后一个 cell.gif
也不是:
这还是全面屏吗?.gif
希望我们都能做一个格物致知的开发者.
来源: http://www.jianshu.com/p/82b692af6858