实验记录
一
// AppDelegate
self.window.rootViewController = [[ViewController alloc] init];
// ViewController
UITableView *tv = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tv.delegate = self;
tv.dataSource = self;
[self.view addSubview:tv];
vc.bouns && 无navbar.png
没有NavBar,没有设置任何东西,最简单情况。左边为iOS 8,右边为iOS 11。发现iOS 8没有向下偏移,iOS 11向下偏移了20像素。
在iOS 11中决定tableView的内容与边缘距离的是adjustedContentInset
属性。
在iOS 11中,新增了安全区域的概念。由于顶部有状态栏,所以系统会自动计算出tv.adjustedContentInset
值为{20, 0, 0, 0}
。从而使得了tv向下偏移20像素。
二
// AppDelegate
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
// ViewController
UITableView *tv = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tv.delegate = self;
tv.dataSource = self;
[self.view addSubview:tv];
vc.bouns && 有navbar.png
两者都向下偏移64像素。
在iOS 11以下,控制器有
automaticallyAdjustsScrollViewInsets
属性,默认为YES。
@property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets
API_DEPRECATED("Use UIScrollView's contentInsetAdjustmentBehavior instead", ios(7.0,11.0),tvos(7.0,11.0)); // Defaults to YES
这个属性设置为YES时,系统会自动把tv向下偏移。
而在iOS 11中,可以看到automaticallyAdjustsScrollViewInsets
属性被废弃,但是为什么仍然向下偏移了64像素呢。原因和一一致,现在的安全区域已经变成了NavBar以下,tv.adjustedContentInset
被改为了{64, 0, 0, 0}
,因此也向下偏移64。
三
// AppDelegate
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
// ViewController
UITableView *tv = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tv.delegate = self;
tv.dataSource = self;
[self.view addSubview:tv];
self.automaticallyAdjustsScrollViewInsets = NO;
vc.bouns && 有navbar && automaticallyAdjustsScrollViewInsets = NO.png
三是二的反例。设置了
self.automaticallyAdjustsScrollViewInsets = NO;
,iOS 11以下不偏移了。
四
// AppDelegate
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
// ViewController
self.tv = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
self.tv.delegate = self;
self.tv.dataSource = self;
[self.view addSubview:self.tv];
if (@available(iOS 11.0, *)) {
self.tv.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
vc.bouns && 有navbar && automaticallyAdjustsScrollViewInsets = NO && UIScrollViewContentInsetAdjustmentNever.png
通过设置tv.contentInsetAdjustmentBehavior
为UIScrollViewContentInsetAdjustmentNever
,可以不让系统计算adjustedContentInset
值。从而使得tv不再偏移。
五
// AppDelegate
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
// ViewController
self.navigationController.navigationBar.hidden = YES;
self.view.backgroundColor = [UIColor yellowColor];
self.tv = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height - 64) style:UITableViewStylePlain];
self.tv.delegate = self;
self.tv.dataSource = self;
[self.view addSubview:self.tv];
y = 64 && hidden NavBar.png
有时候需要自定义导航控制器,这个时候需要把自带的NavBar隐藏。发现在iOS 11以下系统中,tv还是会偏移,并且偏移20像素。而iOS 11就没有问题。
解决办法仍然是设置
automaticallyAdjustsScrollViewInsets
为NO。
iOS 11之前的 automaticallyAdjustsScrollViewInsets
我发现这个属性很有意思。
1 无NavBar
没有设置NavigationController的时候,也就是不存在NavBar的时候,这个属性不会起到作用,tv不会存在偏移问题。
2 有NavBar
2.1 显示NavBar
当设置了NavigationController的时候,并不隐藏NavBar,会默认向下偏移64像素。并且是不管你的NavBar是否遮挡住了tv,都会偏移。下图tv.y = 64
tv,y = 64.png
2.2 不显示NavBar
当设置了NavigationController的时候,并隐藏NavBar,会默认向下偏移20像素。并且和2.1一致,无论tv的frame如何,都会偏移。下图tv.y = 64
tv,y = 64 隐藏NavBar.png
如果你嫌这个属性麻烦,就设为NO,然后手动管理tv的frame。
总结
经过上面的实验,个人认为,有一个比较好的解决UIScrollView偏移问题的方法。就是在代码中加上下面这一段代码:
if (@available(iOS 11.0, *)) {
self.tv.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
这样你就可以为所欲为了,科科。
网友评论
1、ViewController的automaticallyAdjustsScrollViewInsets
2、导航栏半透明navigationBar.translucent
3、UIScrollView的adjustedContentInset
4、到ios11的contentInsetAdjustmentBehavior,
各个版本的适配导航栏问题一直没有整明白,我每次有这种问题时候,都是拿这些点乱搞一通,看看那个能解决问题。
automaticallyAdjustsScrollViewInsets
字面意思是:自动调整scrollview的insets应该指的就是contentInset,
tableview和collectionview都继承自scrollview
所以有导航时偏移64,
有导航,隐藏时,实际上有导航时,导航上面有20间距是状态栏,隐藏了导航,但20间距仍然存在。所以偏移了20.