美文网首页复杂UI疯狂iOS
iOS11适配:关于UITableView的偏移问题记录

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

作者: Jabber_YQ | 来源:发表于2017-11-15 14:49 被阅读866次

    实验记录

    // 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.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];
    
    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;
    }
    

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

    相关文章

      网友评论

      • myk:看到最后虎躯一震,叫我名字:smile:
      • 啊哈呵:从ios7开始了弄了透明的navbar,就开始各种这个偏移的设置:
        1、ViewController的automaticallyAdjustsScrollViewInsets
        2、导航栏半透明navigationBar.translucent
        3、UIScrollView的adjustedContentInset
        4、到ios11的contentInsetAdjustmentBehavior,
        各个版本的适配导航栏问题一直没有整明白,我每次有这种问题时候,都是拿这些点乱搞一通,看看那个能解决问题。
        啊哈呵:@Jabber_YQ 好的,记住这里有秘籍,等再次遇到这问题再回来看看:smile:
        Jabber_YQ:@啊哈呵 我前面还有一片文章也是讲这个的,你可以看看
        Jabber_YQ:@啊哈呵 那这次呢:joy:会用了吗
      • 思念那年慕云:说下个人的理解:
        automaticallyAdjustsScrollViewInsets
        字面意思是:自动调整scrollview的insets应该指的就是contentInset,
        tableview和collectionview都继承自scrollview
        所以有导航时偏移64,
        有导航,隐藏时,实际上有导航时,导航上面有20间距是状态栏,隐藏了导航,但20间距仍然存在。所以偏移了20.
        Jabber_YQ:@思念那年慕云 了解!谢谢:relaxed:
        思念那年慕云:@Jabber_YQ automaticallyAdjustsScrollViewInsets的官方文档: which lets container view controllers know that they should adjust the scroll view insets of this view controller’s view to account for screen areas consumed by a status bar, search bar, navigation bar, toolbar, or tab bar.
        Jabber_YQ:可是奇怪的是,当不存在导航条时,它就不会偏移了,即使遮住了状态栏。

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

      本文链接:https://www.haomeiwen.com/subject/xfhcvxtx.html