iOS 中包含 UIWebView 的单元格的动态 UITableViewCell 高度

Posted

技术标签:

【中文标题】iOS 中包含 UIWebView 的单元格的动态 UITableViewCell 高度【英文标题】:Dynamic UITableViewCell height for a cell that contains a UIWebView in iOS 【发布时间】:2016-12-22 06:41:19 【问题描述】:

我正在尝试将一些 html 资源文件加载到 UITableView 单元格中。我想根据 UIWebView 的内容大小调整单元格高度。以下是我的一些测试代码。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    static NSString *cellIdentifier = @"TableCellID";

    CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil) 
        NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"CustomTableViewCell" owner:self options:nil];
        cell = [nibArray objectAtIndex:0];
    

    NSString *htmlFileName = [NSString stringWithFormat:@"page%ld", (long)indexPath.row];

    NSString *htmlFile = [[NSBundle mainBundle] pathForResource:htmlFileName ofType:@"html"];
    NSString *htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
    [cell.webView loadHTMLString:htmlString baseURL: [[NSBundle mainBundle] bundleURL]];

    return cell;

如果我描述了我的 CustomTableViewCell.xib,它在内容视图中有一个 UIWebView,并且 UIWebView 具有以下约束。

ContentView.Bottom = WebView.Bottom + 8
ContentView.Top = WebView.Top +8
ContentView.Leading = WebView.Leading + 8
ContentView.Trailing = WebView.Trailing + 8

HTML 文件没有 javascript 或 CSS 内容。简单如下。

<html>
    <header>
    </header>
    <body>
        <p>eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee</p>
    </body>
</html>

现在我的输出如下图所示。

正如我在顶部所解释的,我的网页不包含任何 JavaScript。所以我可能无法使用stringByEvaluatingJavaScriptFromString 方法返回文本。

【问题讨论】:

How do I change the height of a table cell that has already loaded?的可能重复 我相信在加载后计算 webview 的高度会更容易,然后让单元格根据 webview 的高度进行调整。 【参考方案1】:

试试这个

- (void)viewDidLoad 
    [super viewDidLoad]; 
    arrOfHTMLList= [[NSMutableArray alloc] init];
    NSMutableDictionary *dic1 = [[NSMutableDictionary alloc] init];
    [dic1 setObject:@"0" forKey:@"height"];
    [dic1 setObject:@"aaaaaaaaaa aaaaaa aaaaaaa aaaaaaa aaaaaa aaaaaa aaaaaaaa aaaaa" forKey:@"htmlString"];

    NSMutableDictionary *dic2 = [[NSMutableDictionary alloc] init];
    [dic1 setObject:@"0" forKey:@"height"];
    [dic1 setObject:@"abababababbabababababab ababab bababa  ababababb" forKey:@"htmlString"];

    NSMutableDictionary *dic3 = [[NSMutableDictionary alloc] init];
    [dic1 setObject:@"0" forKey:@"height"];
    [dic1 setObject:@"sdajdkjas dkasjkhd jkashjkd sakjhdkj askjdaksh dksajkdkjsah djkasjkhd kjsahjkd asjkhdk jasjkdhaskj" forKey:@"htmlString"];

    NSMutableDictionary *dic4 = [[NSMutableDictionary alloc] init];
    [dic1 setObject:@"0" forKey:@"height"];
    [dic1 setObject:@"sdajdkjas dkasjkhd jkashjkd sakjhdkj askjdaksh dksajkdkjsah djkasjkhd kjsahjkd asjkhdk jasjkdhaskj" forKey:@"htmlString"];

    [arrOfHTMLList addObject:dic1];
    [arrOfHTMLList addObject:dic2];
    [arrOfHTMLList addObject:dic3];
    [arrOfHTMLList addObject:dic4];
    


-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    UIWebView *webView = (UIWebView*)[cell viewWithTag:1];
    NSString *myHTML = arrOfHTMLList[indexPath.section][@"htmlString"];
    [webView loadHTMLString:myHTML baseURL:nil];
    webView.delegate = self;
    webView.frame = CGRectMake(0, 0, screenWidth,cell.frame.size.height);
return cell;



-(void)webViewDidFinishLoad:(UIWebView *)webView

    for (UIView *parent=[webView superview];parent!=nil ;parent=[parent superview] )
    
        if([parent isKindOfClass:[UITableViewCell class]])
        
            UITableViewCell *cell=(UITableViewCell *)parent;
            NSIndexPath *indexPath=[_tableView indexPathForCell:cell];
            int height = webView.scrollView.contentSize.height;
            [[arrOfHTMLList objectAtIndex:indexPath.section] setObject:[NSString stringWithFormat:@"%d",height] forKey:@"height"];
            [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
        
    


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    CGFloat height = [arrOfHTMLList[indexPath.section][@"height"] intValue];
    return height;

希望对你有帮助。

【讨论】:

这不起作用,因为 web 视图的框架不能立即适应其 html 内容:) - 仅异步 @Daij-Djan,这应该可以工作,因为它会回调“webView.scrollView.contentSize.height”而不是框架的高度。【参考方案2】:

主要问题是让 web 视图的框架立即适应其 html 内容:) 并且这只发生在它异步加载内容之后!

- (void)webViewDidFinishLoad:(UIWebView  *)aWebView 
     //TODO: update the table's height for the cell for the webview

我编写的一个插入式解决方案是一个自定义 UITableViewCell 子类,它有一个 webview 并通知委托重新加载表格:

https://github.com/Daij-Djan/DDUtils/tree/master/objC/DDUtils-ios/ui/M42WebviewTableViewCell%20%5Bios%5D

最重要的一段代码是:

- (UITableViewCell  *)tableView:(UITableView  *)tableView cellForRowAtIndexPath:(NSIndexPath  *)indexPath 
    M42WebviewTableViewCell *cell = _loadedCells[@(indexPath.row)];
    if (!cell) 
        cell = [[M42WebviewTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];

        NSString *object = _objects[indexPath.row];
        cell.tag = indexPath.row;
        cell.delegate = self;
        [cell setHtml:object AndBaseURL:nil];
    
    return cell;


- (CGFloat)tableView:(UITableView  *)tableView heightForRowAtIndexPath:(NSIndexPath  *)indexPath 
    //if a cell isnt ready, it wont be there and the method will return 0
    M42WebviewTableViewCell *cell = _loadedCells[@(indexPath.row)];
    return cell.height;


#pragma mark - M42WebviewTableViewCellDelegate

- (void)tableCellDidLoadContent:(M42WebviewTableViewCell *)cell 
    if (!_loadedCells) 
        _loadedCells = [[NSMutableDictionary alloc] init];
    
    [_loadedCells setObject:cell forKey:@(cell.tag)];

    //only refresh sizes of rows
    [self.tableView beginUpdates];
    [self.tableView endUpdates];

【讨论】:

【参考方案3】:

我想出了自己的解决方案。但是感谢所有对这个问题发表评论并以不同方式打开我的思想的其他人。所以这就是我所做的。

首先在我的 ViewController 类中添加了一个 UIWebViewDelegate

@interface ViewController () <UITableViewDataSource, UITableViewDelegate, UIWebViewDelegate> 

然后在下面的方法中加载 HTML 页面并添加委托

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

    static NSString *cellIdentifier = @"TableCellID";

    CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil) 

        NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:@"CustomTableViewCell" owner:self options:nil];
        cell = [nibArray objectAtIndex:0];
    

    cell.webView.delegate = self;
    cell.webView.tag = indexPath.row;
    cell.webView.scrollView.scrollEnabled = NO;

    NSString *htmlFileName = [NSString stringWithFormat:@"page%ld", (long)indexPath.row];

    NSString *htmlFile = [[NSBundle mainBundle] pathForResource:htmlFileName ofType:@"html"];
    NSString *htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
    [cell.webView loadHTMLString:htmlString baseURL: [[NSBundle mainBundle] bundleURL]];

    return cell;

加载网页视图后,计算适合其内容的大小,加载所有网页视图后,我重新加载表格数据,如下所示。

- (void)webViewDidFinishLoad:(UIWebView *)webView 

    if (webView.tag == 0) 
        [cellHeightMutArray removeAllObjects];
    

    CGSize fittingSize = [webView sizeThatFits:CGSizeZero];

    [cellHeightMutArray insertObject:@(fittingSize.height) atIndex:webView.tag];

    if (((webView.tag + 1) == dataArray.count) && !reloadedTableViewAfterLoadingWebContent) 

        reloadedTableViewAfterLoadingWebContent = YES;
        _tableView.hidden = NO;

        [_tableView reloadData];
    

然后我调整单元格的高度(这是我遇到的主要问题)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 

    if (cellHeightMutArray.count > 0) 

        return [[cellHeightMutArray objectAtIndex:indexPath.row] intValue];
    

    return 44;

这是我的解决方案,它可以在 iPhone 和 iPad 上完美运行。

但是当我在 iPad 上使用更复杂的用户界面运行它时,我遇到了不同的问题,这是我的真实项目。如果我的解决方案与此问题相关,我会更新此内容。

【讨论】:

以上是关于iOS 中包含 UIWebView 的单元格的动态 UITableViewCell 高度的主要内容,如果未能解决你的问题,请参考以下文章

在tableview ios中使用UILabel的单元格的动态高度

根据内容动态调整tableview单元格的高度 - iOS Swift

在 iOS 的动态框架中包含静态库

调整表格视图单元格以显示 UITextView 和 UIWebView

将动态单元格的表视图内容高度设置为表视图高度约束 ios

当按钮是iOS中自定义单元格的子视图时,如何动态更改按钮文本?