适配iOS 11和iPhone X——导航栏、UITableView

每年的WWDC大会都激动和紧张好一段时间。激动的是期待苹果的新产品带来的那些黑科技,尤其今年的iPhone10周年纪念款iPhone X。紧张的当然是iOS、Swift和Xcode的升级,又要加班了(ㄒoㄒ)。在这里跟大家分享一下适配iOS 11和iPhone X的过程中,遇到了一些坑。

一、导航栏

在解释导航栏变化之前先解释一个iOS 11的新特性:设置大标题,通过BOOL类型的prefersLargeTitles属性来设置。默认设置是不开启。

//显示大标题“设置”

self.navigationController.navigationBar.prefersLargeTitles = YES;

self.navigationItem.title = @"设置";

1
其中LargeTitle还有三种样式可以选择:

UINavigationItemLargeTitleDisplayModeNever//总是显示小标题

UINavigationItemLargeTitleDisplayModeAlways//总是显示大标题

UINavigationItemLargeTitleDisplayModeAutomatic//自动显示大标题或小标题。即初始时是大标题,滑动时大标题隐藏、显示小标题。

通过navigationItem的largeTitleDisplayMode属性来设置:

self.navigationItem.largeTitleDisplayMode =  UINavigationItemLargeTitleDisplayModeAutomatic;

当然,只有当prefersLargeTitles为YES时largeTitleDisplayMode属性才生效。

1、导航栏高度变化

iOS 11之前导航栏默认高度为64pt(statusBar + NavigationBar),iOS11之后如果设置了prefersLargeTitles = YES则为96pt,默认情况下还是64pt。由于iPhoneX上出现了“刘海”,statusBar由以前的20pt变成了44pt,所以iPhoneX上高度变为88pt。

2、导航栏图层变化

iOS 11之前导航栏的title是添加在UINavigationItemView上面的,而navigationBarButton则是直接条件在navigationBar上面。如果设置了titleView,那么titleView也是直接添加在navigationBar上面的。
2

iOS 11之后,视图层级发生了变化,增添了新的管理类。navigationBar会添加在_UIButtonBarStackView上面,而_UIButtonBarStackView则添加在_UINavigationBarContentView上面。
如果没有给titleView赋值,那么titleView会直接添加在_UINavigationBarContentView上面;如果赋值了titlev,那么titleview会添加在_UITAMICAdaptorView上面,_UITAMICAdaptorView会添加在_UINavigationBarContentView上面。
3

这里写图片描述

所以如果你的项目是自定义的navigationBar,那么在iOS11上运行就可能出现布局错乱的bug,解决办法是重写UINavigationBar的layoutSubviews方法,调整布局。

- (void)layoutSubviews {
    [super layoutSubviews];

    //注意导航栏及状态栏高度适配
    self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), naviBarHeight);
    for (UIView *view in self.subviews) {
        if([NSStringFromClass([view class]) containsString:@"Background"]) {
            view.frame = self.bounds;
        }
        else if ([NSStringFromClass([view class]) containsString:@"ContentView"]) {
            CGRect frame = view.frame;
            frame.origin.y = statusBarHeight;
            frame.size.height = self.bounds.size.height - frame.origin.y;
            view.frame = frame;
        }
    }
}

二、UIScrollView、UITableView、UICollectionView

在iOS 11之前,如果想要scrollView不偏移64pt,则设置automaticallyAdjustsScrollViewInsets = NO,现在iOS 11设备上运行出现最多问题应该就是tableview莫名奇妙的偏移20pt或者64pt了。原因就是iOS 11弃用了automaticallyAdjustsScrollViewInsets属性,取而代之的是UIScrollView新增的contentInsetAdjustmentBehavior属性。最终还是因为iOS 11新添了safeArea。

扫描二维码关注公众号,回复: 4065397 查看本文章

另外,tableView的sectionHeader、sectionFooter高度与设置不符的问题,因为在iOS 11中如果不实现

-tableView: viewForHeaderInSection:
-tableView: viewForFooterInSection:

则不会被调用

-tableView: heightForHeaderInSection:
- tableView: heightForFooterInSection:

导致sectionHeader、sectionFooter的高度都变成了默认高度。
iOS 11之前,设置sectionHeader、sectionFooter高度为0时,需要设置height=0.1,才会起作用,如果直接设置为0,则会使用默认高度。在iOS 11中默认使用Self-Sizing,tableView的estimatedRowHeight、estimatedSectionHeaderHeight、 estimatedSectionFooterHeight三个高度估算属性由默认的0变成了UITableViewAutomaticDimension,解决办法简单粗暴,就是实现对应方法或把这三个属性设为0。

如果你使用了Masonry,那么你需要适配safeArea

if (@available(iOS 11.0, *)) {
    make.edges.equalTo()(self.view.safeAreaInsets)
} else {
    make.edges.equalTo()(self.view)
}

猜你喜欢

转载自blog.csdn.net/m403180222/article/details/78849867