步骤和规则
关于顶部是否透明
其实就是导航条引起的,造成原点是否从(0,64)
(ipX的状态栏高度为44,因此是(0,88)
)还是(0,0)
开始
鉴于活动中有一个基类
ActivityBaseViewController
为了便于本次更改,我们统一改为从(0,64)
开始作为原点,因此要更改为
self.extendedLayoutIncludesOpaqueBars = NO;
// 或使用 self.edgesForExtendedLayout = UIRectEdgeBottom 亦可
顶部透明随之而来的
活动的很多viewcontroller
,都直接采用frame
而非约束来绘制控件,这样带来了问题.
由于ipX
和普通的375*667
分辨率的iphone不同
- 安全区域离底部为 34
- 顶部栏的高度从 20+44 变为 44+44
- 屏幕高度从 667 变为 812
所以,建议尽量使用约束来绘制,不使用frame
,以免增加多个宏判断,
已经有一个判断 navHeight, ios7之前是44,之后是64,现在ipX是88
有关安全区域和顶部透明产生的问题
后续的开发就知道,我们常常会用到一个获取安全区域 insets
的函数,来获取安全区域底部的34和顶部的88.
if (@available(iOS 11.0, *)) {
UIEdgeInsets inset = self.view.safeAreaInsets;
}
打印出来的
- inset.bottom = 34;
- inset.top = 88;
但是,如果顶部存在一个不透明的导航栏, 如上所述这时候ipX从(0,88)
开始计算原点, 那么我们取到的inset.top
就会变为0
此时获取这个88的高度,就要使用 获取系统状态栏高度 + 导航栏高度 的做法.
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
CGFloat navBarHeight = self.controller.navigationController.navigationBar.mui_height;
使用masonry约束随之而来的
约束会带来两个问题.
- 约束控件处于安全区域底部
由于旧的设备没有安全区域的概念,因此我们使用self.view.mas_safeAreaLayoutGuideBottom
时,常会出现需要修复的警告⚠️,我们的代码需要变为
if (@available(iOS 11.0, *)) {
make.bottom.equalTo(self.detailMenuView.mas_safeAreaLayoutGuideBottom);
} else {
make.bottom.equalTo(self.detailMenuView.mas_bottom);
}
- 如果当前
viewcontroller
嵌套了一个scrollview
,约束建议这样写
简单来说,就是- 定义一个
scrollview
作为背景容器,他的约束 只和滑动边界edge
约束相关 - 定义一个
UIView
类型的contentview
, 他的约束,两边与self.view
相同,高低与scrollview
相同,然后往contentview
内部添加内容,这样他的高度会自适应.
- 定义一个
UIScrollView *scrollView = [[UIScrollView alloc] init];
[self.view addSubview:scrollView];
[scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(0, 0, 0, 0));
}];
self.scrollView = scrollView;
self.contentView = [[UIView alloc] init];
[self.scrollView addSubview:self.contentView];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.top.bottom.equalTo(self.scrollView);
}];
- 如果当前
viewcontroller
内含有scrollview
及其子类,必须要添加
if (@available(iOS 11.0, *)) {
self.tableView.contentInsetAdjustmentBehavior = UIApplicationBackgroundFetchIntervalNever;
}
否则会出现 前一个包含scrollview
的类,滑动回来的时候顶部出现真空偏移.
底部上拉刷新是否显示"没有更多数据"
还分两种情况,
- 一种是tableview直接包含底部
- 一种是tableview底下还有一个按键(没有透下去)
普通机型(375*667
)的iPhone
iPhone X加了偏移前后对比
修改的原则
- 判断当前设备是否为 ipX(这次通过安全区域的偏移)
- 判断当前页面是否为 非一级页面(ND特殊要求, 一级页面底部一定有tab栏,不用不会产生适配可能的冲突)
- (void)viewSafeAreaInsetsDidChange {
[super viewSafeAreaInsetsDidChange];
if (@available(iOS 11.0, *)) {
UIEdgeInsets inset = self.view.safeAreaInsets;
// 判断当前页面为非一级页面 且 设备是ipX
if (self.navigationController.viewControllers.count > 1 && inset.bottom > 0) {
CGFloat msgLabelHeight = ((MUILoadMoreContentView *)self.tableView.mui_loadMoreControl.containView).messageLabel.mui_height;
[self setCollectionContentInsetBottom:inset.bottom + msgLabelHeight + 5];
}
}
}
- (void)setCollectionContentInsetBottom:(CGFloat)bottom {
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, bottom, 0);
self.tableView.mui_refreshControl.originalContentInsetBottom = bottom;
self.tableView.mui_loadMoreControl.originalContentInsetBottom = bottom;
}