iOS 中包含 UIWebView 的单元格的动态 UITableViewCell 高度
Dynamic UITableViewCell height for a cell that contains a UIWebView in iOS
我想做的是将一些 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 fils 没有 JavaScript 或 CSS 内容。简单如下。
<html>
<header>
</header>
<body>
<p>eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee</p>
</body>
</html>
现在我的输出如下图。
正如我在顶部所解释的,我的网页不包含任何 JavaScript。所以我可能无法使用 stringByEvaluatingJavaScriptFromString
方法来 return 文本。
试试这个
- (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;
}
希望对您有所帮助。
主要问题是让网络视图的框架立即适应其 html 内容 :)
并且只有在它异步加载内容后才会发生!
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
//TODO: update the table's height for the cell for the webview
}
我写的一个嵌入式解决方案是一个自定义的 UITableViewCell 子类,它有一个 webview 并通知委托重新加载 table:
最重要的一段代码是:
- (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];
}
我想出了自己的解决方案。但是感谢所有其他对这个问题发表评论并以不同的方式打开我的思路的人。这就是我所做的。
首先添加了一个 UIWebViewDelegate 到我的 ViewController class
@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;
}
加载网络视图后,计算适合其内容的大小,加载所有网络视图后,我重新加载 table 数据,如下所示。
- (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 中使用更复杂的用户界面时,我遇到了不同的问题。如果我对与此问题相关的问题的解决方案,我会更新此内容。
我想做的是将一些 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 fils 没有 JavaScript 或 CSS 内容。简单如下。
<html>
<header>
</header>
<body>
<p>eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee eeeee</p>
</body>
</html>
现在我的输出如下图。
正如我在顶部所解释的,我的网页不包含任何 JavaScript。所以我可能无法使用 stringByEvaluatingJavaScriptFromString
方法来 return 文本。
试试这个
- (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;
}
希望对您有所帮助。
主要问题是让网络视图的框架立即适应其 html 内容 :) 并且只有在它异步加载内容后才会发生!
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
//TODO: update the table's height for the cell for the webview
}
我写的一个嵌入式解决方案是一个自定义的 UITableViewCell 子类,它有一个 webview 并通知委托重新加载 table:
最重要的一段代码是:
- (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];
}
我想出了自己的解决方案。但是感谢所有其他对这个问题发表评论并以不同的方式打开我的思路的人。这就是我所做的。
首先添加了一个 UIWebViewDelegate 到我的 ViewController class
@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;
}
加载网络视图后,计算适合其内容的大小,加载所有网络视图后,我重新加载 table 数据,如下所示。
- (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 中使用更复杂的用户界面时,我遇到了不同的问题。如果我对与此问题相关的问题的解决方案,我会更新此内容。