带有 UIWebview 的 UITableViewCell,可根据内容大小调整高度

Posted

技术标签:

【中文标题】带有 UIWebview 的 UITableViewCell,可根据内容大小调整高度【英文标题】:UITableViewCell with UIWebview that adjusts height to content size 【发布时间】:2016-06-01 22:04:37 【问题描述】:

因此,我从 API 中提取了一个 html 字符串,并尝试将其加载到 UITableViewCell 中的 UIWebView 中,并且内容在单元格中滚动。我需要让 webview 的高度适应内容的大小,然后相应地调整单元格。我在这里迅速找到了一个帖子: UITableViewCell With UIWebView Dynamic Height 我尝试做同样的事情,但我遇到了一些麻烦,因为我使用 NSMutableArray 来存储带有浮点数的 NSNumber,然后尝试将其加载,但 cellForRowAtIndexPath 和 heightForRowAtIndexPath 都在调用 webview 委托方法之前执行,所以我会得到一个索引超出范围错误。

到目前为止,我有这个:

@interface FGCThreadDetailTableViewController ()

@property (copy, nonatomic) NSArray<FGCThreadModel*>* threads;
@property (copy, nonatomic) NSMutableArray* contentHeights;

@end

@implementation FGCThreadDetailTableViewController

- (void)viewDidLoad 
    [super viewDidLoad];
    [self.tableView registerClass:[FGCThreadDetailCell class] forCellReuseIdentifier:@"threadDetailCell"];
    self.tableView.estimatedRowHeight = 100;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    [SVProgressHUD show];
    [[FGCThread postsByThreadID:_threadID] subscribeNext:^(id x) 
        _threads = x;
        [SVProgressHUD dismiss];
        [self.tableView reloadData];
    ];
    _contentHeights = [[NSMutableArray alloc] init];


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    return 1;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    return _threads.count;


- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    FGCThreadDetailCell* cell = [tableView dequeueReusableCellWithIdentifier:@"threadDetailCell" forIndexPath:indexPath];
    FGCThreadModel* thread = _threads[indexPath.row];
    cell.webView.delegate = self;
    CGFloat htmlHeight;
    htmlHeight = [_contentHeights[indexPath.row] floatValue];
    cell.webView.tag = indexPath.row;
    [cell.webView loadHTMLString:thread.postBodyHTMLString baseURL:nil];
    cell.webView.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight);
    return cell;


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
    return [_contentHeights[indexPath.row] floatValue];


- (void)webViewDidFinishLoad:(UIWebView *)webView 
    if (_contentHeights[webView.tag]) 
        return;
    
    _contentHeights[webView.tag] = [NSNumber numberWithFloat:[[webView stringByEvaluatingjavascriptFromString:@"document.body.offsetHeight;"] floatValue]];
    [self.tableView reloadData];


@end

提前致谢!

【问题讨论】:

你能添加一些代码来帮助你吗? @ReinierMelian 添加了。谢谢! 我想知道您是否可以使用动态单元格高度,并使用自动布局约束来调整单元格的大小。在您的webViewDidFinishLoad 中,您可以更新constant 上相应单元格的高度约束。可能比存储高度更容易。 @DylanS 我不确定我明白你的意思......我知道我怎么能做到这一点。我正在使用动态单元格高度,但我在 webview 完成加载时不能做太多事情,因为如果我在高度更新后将重新加载数据放在那里,它将导致循环。 你不想在那个方法中reloadData。使用动态单元格高度,您可以随时调整单元格高度,表格将更新。您可以向单元格添加自动布局约束,使其高度必须等于 Web 视图高度吗?然后您可以在webViewDidFinishLoad 中更新网络视图的高度。您还需要删除 heightForRowAtIndexPath 的实现,以便表格视图使用单元格的高度。 【参考方案1】:

自动布局方法可能很棘手。一种更简单的方法是在webViewDidFinishLoad 中设置相应单元格的框架。您可以在表格视图上使用cellForRowAtIndexPath 来获取显示的单元格(如果它已经显示,它不会尝试从UITableViewDataSource 获取单元格,因为它会被缓存)。

- (void)webViewDidFinishLoad:(UIWebView *)webView 
    if (_contentHeights[webView.tag]) 
        return;
    
    float height = [NSNumber numberWithFloat:[[webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight;"] floatValue]];

    NSIndexPath* indexOfCell = [NSIndexPath indexPathForRow:webView.tag inSection:0];
    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexOfCell];
    cell.frame = CGRectMake(0, 0, cell.frame.size.width, height);

【讨论】:

所以基本上这就是我开始做的事情......但问题是当它试图评估_contentHeights[webView.tag]时它会抛出异常,因为其中不会有第一个或第二个元素数组是我原来的问题。 @TylerRister 删除了 _contentsHeight,因为它不应该存在。您不能在heightForRowAtIndexPath 中使用_contentsHeight,因为它不可能有高度,所以只需使用自动单元格高度。

以上是关于带有 UIWebview 的 UITableViewCell,可根据内容大小调整高度的主要内容,如果未能解决你的问题,请参考以下文章

带有 UINavigationBar 的 UIPageViewController 内的 UIWebView

使用 loadData 时提供带有查询字符串的 UIWebview

带有分页的全屏 UICollectionView 内的 UIWebView

使用带有缩放功能的 UIWebView 显示 Google 地图

带有 UIWebview 的 UITableViewCell,可根据内容大小调整高度

UIWebView 中的本地 html,带有来自资产目录的图像