如何让UITableHeaderView的高度自适应

作者: flightlessBirdT | 来源:发表于2016-08-05 15:59 被阅读7532次

相信很多iOS开发者都有一些困惑,当我们需要在UITableView中实现一些复杂的界面效果时,除了通常能想到的UITableViewCell的self-sizeing。其实UITableViewHeaderView也是能够充分利用起来的。但是关于用UITableViewHeaderView去实现一些复杂效果的时候,最大的坑在于UITableView并不会根据UITableViewHeaderView的高度去动态调整自己的高度,举个列子来说吧:比如当你初始化一个高度为100的headerView作为UITableViewHeaderView时,当你再通过代码去设置headerView的高度时是没有用的。这里的解决办法是重新替换一个新的UITableViewHeaderView。本文将结合笔者自己项目中的需求来和大家探讨一下如何实现UITableViewHeaderView的高度自适应。

先看一下我项目中实现的效果

IMG_3286.PNG IMG_3288.PNG IMG_3287.PNG

我的页面布局就是一个UITableView。整个页面布局分为两套。第一套是笔记内容。第二套是笔记评论。那笔记内容里面包括富文本,图片,附件等视图。如果全部都用UITableViewCell来实现的话也是可以的,那笔记内容整体作为一个单独的Cell去处理。但是当笔记内容的View为UIWebView的时候,事情就不像这么简单了。

首先如果你用UITableViewCell去嵌入一个UIWebView的时候,处理起来是非常麻烦的。因为你要考虑到高度回调的问题。因为只要网络不好,UIWebView可能一直在加载,UITableView就没法拿到准确的高度。而且当你需要处理的视图不单单是UIWebView的时候,会更麻烦。所以通常情况来讲,这种页面布局推荐使用UITableViewHeaderView去完成布局时最好的。

比如首先拆分笔记内容里的视图:富文本视图 图片视图 附件视图。那笔记评论是一个个高度自适应的cell。这里面

其实我这个项目布局的最大难点不在于UITableHeaderView的高度自适应,只是在网上看到很多人棘手于这个问题,就写一下解决办法吧,然后再说一下我项目中的难点,希望可以帮到有相同问题的人。

首先,我需要在headerView中放入很多东西,比如文章的作者信息与发布时间啥的,这是一个view,然后是文章内容,这是一个UIWebView,最后是一些为了美观设计的一些控件图,这里就当做一个view来看吧。

    UIView *view=self.mainTableView.tableHeaderView;
    view.frame = CGRectMake(0,0,ScreenW,self.webView.height+56+30+52+20);
    self.mainTableView.tableHeaderView = view;

如果你需要展示的网页是基本本地html文件里的css文件(可能是外链接的css可能是本地的css文件,但是这个不影响),你是需要先让UIWebView加载本地的html文件的,然后让它显示要展示的内容,这里问题来了,webViewDidFinishLoad方法在第一次加载html文件时就会执行,以后除非你reload网页,否则此方法也不会执行的。而且,就算你reload网页里,你会发现你获取到的高度依然是其初始化时设置的高度。那如何获取webView加载完的高度呢?此时你就需要强大的KVO来帮你啦!在-(void)webViewDidFinishLoad:(UIWebView *)webView对webView增加监听:

if (!self.isObserving) {
    [self startObservingHeight];
}

- (void)startObservingHeight
{
[self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
self.isObserving = YES;
}

- (void)stopObservingHeight
{
[self.webView.scrollView removeObserver:self forKeyPath:@"contentSize" context:nil];
self.isObserving = NO;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:  (id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"contentSize"]) {
    NSLog(@"监听变化%@",[change objectForKey:@"new"]);
    //        NSStringFromCGSize([change objectForKey:@"new"]);
    self.webView.height = self.webView.scrollView.contentSize.height;
    UIView *view=self.mainTableView.tableHeaderView;
    view.frame = CGRectMake(0,0,ScreenW,self.webView.height+56+30+52+20);
    
    [self.webView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.headerView).offset(20);
        make.right.equalTo(self.headerView).offset(-20);
        make.top.equalTo(self.headView.mas_bottom);
        make.height.equalTo(@(self.webView.height));
    }];
    
    self.mainTableView.tableHeaderView = view;
    
}
}

这样就可以达到效果了。
此方法是动态的监听webView的高度,然后通过自动布局完成自适应。

相关文章

网友评论

  • Yaanco:使用SDAutolayout自动计算高度也挺方便的,
  • 西门欥雪:大神,headerView上放轮播图和一个介绍信息的Label(信息不同),使用Masonry怎么动态的获取高呢。
  • 向钱冲啊:文章重点是:flushed:介绍怎么获取webview高度的。
    flightlessBirdT:@向钱冲啊 :flushed::flushed:
  • Anyeler:还有一个可以用回调设置
    flightlessBirdT:@Anyeler 不可以 直接设置frame是无效的 只能重新获取frame 然后初始化一个view 设置成新的headerView :smile:
    Anyeler:@flightlessBirdT headerview可以通过回调直接设置它高度也是生效的吧?
    flightlessBirdT:@Anyeler 感谢分享你的建议:smile: 如果cell内嵌的话回调是可以的 headerView只能重新设置view

本文标题:如何让UITableHeaderView的高度自适应

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