缘起:
界面结构比较简单即UIViewController的UIView中包含一个UITableView。我们想要的是隐藏导航栏,之后将UIView和UITableView显示在屏幕的最顶端位置,即y坐标为0.
目标如下图所示:
实现:
当这个UIViewController被push到navigationController的导航栈(viewControllers
)中后,在viewDidLoad()函数里书写如下代码:
// 隐藏导航栏
self.navigationController?.setNavigationBarHidden(true, animated: true)
// 将UIView的显示移动到顶部,即从原有导航栏的起始位置显示UIView,从屏幕的最顶端显示UIView
self.edgesForExtendedLayout = UIRectEdge.top
tableView的生成代码如下
func setUpViews() {
self.view.addSubview(tableView)
tableView.mas_makeConstraints { (make) in
make?.edges.equalTo()(self.view)?.with()?.insets()(UIEdgeInsets.zero)
}
}
运行程序,UIViewController的View会显示在界面的最顶部即y坐标为0,但是Tableview的起始位置并未和View的位置对齐,距离View顶部有一个导航栏的距离。运行效果如下图所示:
我们预计的是将UITableView也显示在导航栏的底部,上面代码未能实现,这是为啥呢?难道是TableView的frame的y坐标不对?
问题查找:
于是我们在viewDidLayoutSubviews()函数内打断点,打印TableView,内容入下所示:
<UITableView: 0x108e46800; frame = (0 0; 375 812); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x2815ef540>; layer = <CALayer: 0x2843fb100>; contentOffset: {0, -88}; contentSize: {375, 0}; adjustedContentInset: {88, 0, 74.666666666666671, 0}; dataSource: <iReader.ZYLibraryAlbumViewController: 0x108e40e00>>
我们可以看到UITableView的frame坐标的起始位置都是(0, 0)。证明frame没问题。我们看到ContentInset的top为88,这就是问题所在了,我们用iPhone XS Max做的测试,该设备的导航栏的高度就是88。UITableView自动设置了其ContentInset, 我们找到原因了,但是怎么解决呢?
解决办法:
最直接的办法是在viewDidLayoutSubviews()函数内设置UITableView的contentInset的top为0,但是总感觉这么做不够优雅。
[self.tableView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
优雅的解法:
于是找到了如下方法,在viewDidLoad()函数增加如下代码:
self.edgesForExtendedLayout = UIRectEdge.top
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
运行程序,UITableView和UIView的起始位置都在屏幕的最顶端,问题解决了。
原因探索:
下面我们看下加的contentInsetAdjustmentBehavior方法是什么意思,打开文档我们发现contentInsetAdjustmentBehavior是UIScrollView类的方法,该方法的作用和名称的表面含义差不多,即是否根据安全区等信息来自动设置ContentInset。我们将其设置为.never,即不让其自动设置ContentInset。文档内容如下:
contentInset。 This property specifies how the safe area insets are
used to modify the content area of the scroll view. The default value
of this property is
UIScrollView.ContentInsetAdjustmentBehavior.automatic.
参考链接:
https://www.generacodice.com/en/articolo/2196847/set-uitableview-content-inset-permanently
https://stackoverflow.com/questions/38613879/uitableview-is-under-the-tabbar