IOS TableViewCell嵌套webview

作者: kuazi | 来源:发表于2015-11-13 11:49 被阅读16930次
IMG_0521.JPG

新项目中,遇到了一个新的需求:tableview中一个cell里嵌套了web view,想让web view根据内容自适应高度,cell根据webView自适应高度。
对于这个需求,我们只要2步就可以完成。

1.如何获取webview的高度

webview的高度,我从http://stackoverflow.com/questions/7341767/ios-resize-uiwebview-to-fit-content
http://www.xuebuyuan.com/2035051.html
找到了答案。

    //获取到webview的高度
    CGFloat height = [[self.webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] floatValue];

2.获取到webview的高度,重新reloadTableview就可以

- (void)viewDidLoad {
    [super viewDidLoad];
    _webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, 1)];
    _webView.delegate = self;
    _webView.scrollView.scrollEnabled = NO;
    //预先加载url
    [self.webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://www.baidu.com/"]]];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - TableViewDelegate & TableViewDatasource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return  3;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 1){
        static NSString *identifier = @"cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
        if (!cell){
            cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
            [cell.contentView addSubview:_webView];
            /* 忽略点击效果 */
            [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
        }
        return cell;
    }else{
        static NSString *identifier = @"cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
        if (!cell){
            cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
        }
        cell.textLabel.text = [NSString stringWithFormat:@"index====%ld",(long)indexPath.row];
        return cell;
    }
    
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
    if(indexPath.row == 1){
        /* 通过webview代理获取到内容高度后,将内容高度设置为cell的高 */
        return _webView.frame.size.height;
    }else{
        return 100;
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

#pragma mark - UIWebView Delegate Methods
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
    //获取到webview的高度
    CGFloat height = [[self.webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] floatValue];
    self.webView.frame = CGRectMake(self.webView.frame.origin.x,self.webView.frame.origin.y, kScreenWidth, height);
    [self.tableView reloadData];
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
    NSLog(@"webViewDidStartLoad");
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error
{
    NSLog(@"didFailLoadWithError===%@", error);
}
效果图

PS

demo地址,请猛戳这里
//备注
这个方法是我之前的解决方案,这方案实现起来不好,有bug。 可以去看看DTCoreText这个库(https://github.com/Cocoanetics/DTCoreText

相关文章

网友评论

  • VickyLanLan:'DTFoundation/DTWeakSupport.h' file not found这个文件没找着?项目运行不起来
  • Beyond无状态:楼主怎么解决嵌套的手势冲突
  • DZIR:你的cell用了注册单元格但是在代理里面又判断当没有cell的时候才给cell的contentview加webview所以这个webview根本没加到cell上面,我看到有条评论说加载出来的webview是空白那是因为根本没加上去,这里的代码你自己跑一下会把webview加载上去吗?
  • z益达:你这样死循环了,会不停的reloadData
  • Ko_Neko:webView放进Cell是个巨坑。。。因为如果常规在cellforRowatIndexPath里用model的形式为Cell赋值之后重写setter加载网页。那么每次Cell滚动都会走这个方法导致无限load网页最后崩溃。。而且确实会出现莫名其妙的空白……
    kuazi:只适用简单的webview。 如果复杂的可以看下我PS里写的 DTCoreText。
    yunxiu:求问怎么解决啊?
  • 一起走过的黑夜变一地白雪:cell上嵌套WebView的一系列问题解决了吗?
  • SvenDai:楼主想问一个问题,在webview中渲染了网页之后点击网页中的链接跳转到另一个网页出现的是白屏是怎么回事?
    SvenDai:@kuazi 看上去是先渲染了一下之后又消失白屏了,看了一下log是链接中有多级跳转的时候会发生这种情况,楼主有解决办法么,还有个问题是有些html文件捕获不到高度
    kuazi:你看下新的网页 渲染了吗
  • 羊肉泡馍啊:这样tableView会有卡顿
    kuazi:卡顿没测试过。
  • 追赶阳光:一般网页放cell里面不多见吧,滑动cell重用会重新加载,我项目里面是直接把网页的写成静态cell的。
    追赶阳光:@大白李 简单的方法就是持有它,不释放
    加拉隆的深渊之核:怎么直接把网页写成静态cell呀
    kuazi:@追赶阳光 这种就是特殊需求。
  • feng_dev:图片的 字写得超级棒!
    kuazi:@伤感的小孩 😝😝
  • hhgvg:你好 我想问一下就是你的webview自适应高度有20000高度,这个怎么处理呢
    kuazi:@hhgvg 能把那个链接发下吗?
    hhgvg:@kuazi 是加载网站上的链接 这个链接里面的高度有20000多 然后加载的时候app就crash了
    kuazi:@hhgvg 就是h5的高度是20000吗?
  • 黄大大很大:这么做加载图片过多,内存峰值会超过限制导致crash
    kuazi:@sunbox 具体什么需求
    黄大大很大:@kuazi 现在正在做类似的项目,一直没有找到好的解决方案。请教,这种需求用什么方案能保证良好的用户体验。
    kuazi:@sunbox 当网页图片过多的时候,就不会做这种解决方案了。
  • 曲非烟:你彻底帮死我了 (*  ̄3)(ε ̄ *)
  • 啊全全:如果我的cell上添加一个 uiwebview 只是加载一个图片 我想点击这个cell 进入到下一个界面 但是webview 挡住了 设置了 交互性也不行 有没有什么办法可以弄
    ca1b5ddc1a34:只是一个图片为啥不用imageview
    kuazi:@啊全全 那没必要用webview图片吧。你可以用- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {这个方法把事件传递一直是cell就行
  • kuazi:后来 我找到更好的解决方案 : 获取 webview的高度,可以通过kvo监听webview的scrollview的contentSize。
    加拉隆的深渊之核:@milk_hz 有cell自适应webview的Demo吗?
    kuazi:@milk_hz 恩,我要找个时间,用这个方法重新写下,博客的方法不是很好
    ca1b5ddc1a34:我就是用的这个方法
  • zlcode:如果webView.scalesPageToFit = YES时计算的高度不准确。http://blog.zlcode.com/2016/04/28/ios-webview-cell/
  • 97227b8677ae:我们项目里也是这样实现的,请问如果网页中图片过多时如何优化加载速度
    kuazi:@soap君灬 可以先加载文字,再加载图片。 调用js方法
  • 81ee005f7a77:我的请求的是html的数据不会自适应!怎么解决这个问题啊?
    kuazi:@81ee005f7a77 html数据跟网页一样的,应该可以拿到高度的。 能麻烦发下你的html数据吗
  • 若锦:我的tableview有四个cell,第一个cell放的webview,由于一开始还没能得到高度,所以下面的cell的内容会覆盖在webview上,看起来好乱,用手滑动一下之后才正常,有没有什么好的建议去解决一下这个问题呢
    若锦: @kuazi 嘿嘿,没关系,谢谢你,但是我需要自适应高度呢,给固定的屏幕高度的话还能自适应不
    kuazi:@雨汐流若 不好意思,刚看到 。您可以让webview的高度是屏幕的高度,然后在webview上加个loading。 可以让用户有更好的体验
  • 匿名类:这是个大坑,网页里图片多了会崩的
    无厌_:崩了怎么办呢,求问大神
    kuazi:@sunbox 嗯,这个确实是出现。但是网页图片过多的时候,就不会做这种解决方案了。
    黄大大很大:@匿名类 遇见个明白人
  • 96ba08882163:你这这样写不会进入死循环吗? 你在loadfinish里reloadtableview ,tableviewreload的时候会有加载一遍webview,这不就进入死循环了吗?
    Susisebsby:@飘渺阿天 我想你们的区别在于,你在cell里面 loadRequest,而楼主是在viewdidLoad里面预先加载的webview,在reloadData的时候 cell就没有loadRequest,就不存在死循环了,我也陷入死循环了,因为我也在cell里面loadRequest
    飘渺阿天:肯定会死循环的,已测试
    kuazi:@DoubleY丶 不会死循环啊。tableview 刷新,只是为了改变高度,不会重新加载webview的。
  • 93d451992f07:cell的复用不会乱么? 我改成了15个滚动之后就乱了呢!
    kuazi:@lee_retain 我这提供解决思路,如果有更好的方法和思路,可以探讨下
    93d451992f07:@kuazi :grin:
    kuazi:@lee_retain 嗯,我这也乱了。 但是问题是正常的需求是不会一个控制器 里面有5个webview的。
  • 喵小萌公主:我的url是我们后台返回的,计算不出webView的高度呢,需要怎么弄?谢谢啦。
    kuazi:@喵小萌公主 能麻烦发下url
    喵小萌公主:照样调用代理方法,我把你的demo下载下来后百度的链接换成我们自己的url 也是计算不出高度,我不知道这是怎么回事,希望楼主帮忙解答一下,非常感谢。
    kuazi:服务器返回的url也照样调用代理方法。
  • 杜若玲玲:楼主,为什么我按照你的写,webVIew的代理方法不走呢?这样就没有办法获取webView的高度了,很着急,希望楼主看到后,帮忙答疑一下吧
    kuazi:你url是什么
    杜若玲玲:@kuazi 是这里的链接吗,我已经下了,但是,我请求下来的webVIew是可以滚动的类型图片展示,用楼主的这个,我写的一模一样,但是就是不去调用webVIewDI d FI ni d h的那么方法,求解,感激不尽啊,坐等答复
    kuazi:可以看下我的demo
  • 没梦想的咸鱼2:网页中有下拉按钮的话,点击后webView高度变化,但是不会回调webViewDidFinishLoad
    这种情况貌似只能js去回调个oc方法进行刷新Cell高度~
    项目要支持iOS6 绑定个js,好麻烦,还要修改js代码,非常蛋疼,来讨论讨论~
  • ae7932ac6ffc:楼主,按照这个写法,我刷新表格的时候有时候很慢,得等十几二十秒或者更长,还有webview加到cell上之后,有的时候会出现一片空白区域,这又怎么解决呢?有解决办法,请联系1458538925扣扣,多谢
    kuazi:@a群 这个方法是我之前的解决方案,这方案实现起来不好,有bug。 可以去看看DTCoreText这个库(https://github.com/Cocoanetics/DTCoreText)
    a群:@kuazi 我当前 使用 kvo监听 获取高度 偶发 滚动过程 出现 是空白的 , 当 当前屏幕在往下滚动才载入 webViewCell 的时候 复现概率大一些。 得到新高度 使用 reloadData 方式 因为 只刷新一行 或者 一组 会因为 webViewCell 还没在当前屏幕呢 刷新失效 滚动 到webViewCell时候 高度已不能再刷新了明显复现的手机是 6s这种小屏的
    kuazi:@我不是你的诗人 在获取到webview的高度的时候,我这里写的reload。 实际上应该只刷新有webview的cell(reloadRowsAtIndexPaths)。webview加到cell,会出现空白的区域,这个怎么产生的?
  • 然然啊:我想知道如果每个cell里面都有webview,应该怎么解决
    kuazi:@然然啊 什么需求。必须webview吗
    然然啊:@kuazi 我就遇到了,可以告诉我解决方案吗?
    kuazi:@然然啊 我的理解,应该不会有每个cell都有webview。因为webview本来就耗内存。多个webview这种情况很少出现吧。

本文标题:IOS TableViewCell嵌套webview

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