iOS11适配:关于UITableView的偏移问题记录

实验记录

// 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];
iOS11适配:关于UITableView的偏移问题记录_第1张图片
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];

iOS11适配:关于UITableView的偏移问题记录_第2张图片
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;

iOS11适配:关于UITableView的偏移问题记录_第3张图片
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;
}
iOS11适配:关于UITableView的偏移问题记录_第4张图片
vc.bouns && 有navbar && automaticallyAdjustsScrollViewInsets = NO && UIScrollViewContentInsetAdjustmentNever.png

通过设置tv.contentInsetAdjustmentBehaviorUIScrollViewContentInsetAdjustmentNever,可以不让系统计算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];

iOS11适配:关于UITableView的偏移问题记录_第5张图片
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


iOS11适配:关于UITableView的偏移问题记录_第6张图片
tv,y = 64.png

2.2 不显示NavBar

当设置了NavigationController的时候,并隐藏NavBar,会默认向下偏移20像素。并且和2.1一致,无论tv的frame如何,都会偏移。下图tv.y = 64


iOS11适配:关于UITableView的偏移问题记录_第7张图片
tv,y = 64 隐藏NavBar.png

如果你嫌这个属性麻烦,就设为NO,然后手动管理tv的frame。

总结

经过上面的实验,个人认为,有一个比较好的解决UIScrollView偏移问题的方法。就是在代码中加上下面这一段代码:

if (@available(iOS 11.0, *)) {
    self.tv.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
    self.automaticallyAdjustsScrollViewInsets = NO;
}

这样你就可以为所欲为了,科科。

你可能感兴趣的:(iOS11适配:关于UITableView的偏移问题记录)