将 UIWebView 转换为具有动态大小的 UITableViewCell
UIWebView into a UITableViewCell with dynamic size
我有 UIWebView
个对象成倍数 UITableViewCell
。每个 webView 都有不同的大小。最初,所有单元格的高度都相同。一旦用户触摸单元格,它就会展开以显示所有 webView 内容。
我正在使用 - (void) webViewDidFinishLoad:(UIWebView *)aWebView
动态获取 webView 高度,并使用 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
调整单元格大小。但是,webViewDidFinishLoad
仅在调整大小方法之后调用,因此,调整大小是使用 webView 高度的旧值进行的。
我尝试按所需顺序手动调用这两种方法,但它确实有效(我认为我根本不应该这样做,无论如何...)。
这是我将 Web 视图加载到每个单元格中的代码:
[self.webView setUserInteractionEnabled:NO];
[self.webView loadHTMLString:finalString baseURL:nil];
[cell addSubview:self.webView];
cell.accessoryView = accessoryLabel;
cell.textLabel.text = nil;
self.selectedRowIndex = indexPath.row;
[tableView beginUpdates];
[tableView endUpdates];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
要动态获取像元大小:
- (void) webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
frame.size.height = 1;
aWebView.frame = frame;
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
self.cellSize = fittingSize.height;
NSLog(@"Calling webViewDidFinishLoad. Cell size value: %lf", self.cellSize);
}
要更改单元格大小:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath {
if(indexPath.row == self.selectedRowIndex) {
NSLog(@"Resizing cell with size: %lf", self.cellSize);
return self.cellSize + 10;
}
return 44;
}
输出结果如下:
2015-02-24 22:59:08.902 testProject[62200:2703641] Resizing cell with size: 0.000000
2015-02-24 22:59:09.064 testProject[62200:2703641] Calling webViewDidFinishLoad. Cell size value: 501.000000
有没有办法只在 webViewDidFinishLoad
执行后调整单元格的大小?
非常感谢任何帮助!!
我很好奇这是否与您做事的顺序有关。你能尝试这样做吗:
[cell addSubview:self.webView];
self.webView.frame = ... create frame with cell width and height set to 1 ...
[self.webView loadHTMLString:finalString baseURL:nil];
我仍然不知道为什么会这样,但我使用以下方法解决了它:
我将 [tableView beginUpdates]
和 [tableView endUpdates]
指令移至 webViewDidFinishLoad
方法。这样,每当执行 webViewDidFinishLoad
时,它都会正确更新单元格大小。虽然我认为这不是最好的解决方案,但它确实有效。
现在,我的 webViewDidFinishLoad
方法如下所示:
- (void) webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
frame.size.height = 1;
aWebView.frame = frame;
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
self.cellSize = fittingSize.height;
[self.tableView beginUpdates];
[self.tableView endUpdates];
NSLog(@"Calling webViewDidFinishLoad. Cell size value: %lf", self.cellSize);
}
也许答案可以帮助遇到类似问题的其他人。
我的工作解决方案是使用 KVO。小心移除观察者。在 didEndDisplayingCell
或 viewWillDisappear
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.webview.addObserver(self, forKeyPath: "scrollView.contentSize", options: NSKeyValueObservingOptions.New, context: &context)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String: AnyObject]?, context: UnsafeMutablePointer<Void>) {
if let webview = object as? UIWebView {
let cs = webview.scrollView.contentSize
}
}
防止死循环。关键是如果你已经得到了 webview 的高度,只需 return 在 webViewDidFinishLoad 方法中。我的 webViewDidFinishLoad 看起来像这样:
// If the height is already exist, just return to prevent the infinite loop
// The default height is 0.0
if ([[self.webviewHeightDic objectForKey:[NSString stringWithFormat:@"%ld",(long)webView.tag]] floatValue] != 0.0) {
return;
}
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
NSLog(@"Cell height = %f ",fittingSize.height);
// Set the height to the target webview
[self.webviewHeightDic setObject:[NSNumber numberWithFloat:fittingSize.height]
forKey:[NSString stringWithFormat:@"%ld",(long)webView.tag]];
// Refresh the tableView
[self reloadData];
我有 UIWebView
个对象成倍数 UITableViewCell
。每个 webView 都有不同的大小。最初,所有单元格的高度都相同。一旦用户触摸单元格,它就会展开以显示所有 webView 内容。
我正在使用 - (void) webViewDidFinishLoad:(UIWebView *)aWebView
动态获取 webView 高度,并使用 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
调整单元格大小。但是,webViewDidFinishLoad
仅在调整大小方法之后调用,因此,调整大小是使用 webView 高度的旧值进行的。
我尝试按所需顺序手动调用这两种方法,但它确实有效(我认为我根本不应该这样做,无论如何...)。
这是我将 Web 视图加载到每个单元格中的代码:
[self.webView setUserInteractionEnabled:NO];
[self.webView loadHTMLString:finalString baseURL:nil];
[cell addSubview:self.webView];
cell.accessoryView = accessoryLabel;
cell.textLabel.text = nil;
self.selectedRowIndex = indexPath.row;
[tableView beginUpdates];
[tableView endUpdates];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
要动态获取像元大小:
- (void) webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
frame.size.height = 1;
aWebView.frame = frame;
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
self.cellSize = fittingSize.height;
NSLog(@"Calling webViewDidFinishLoad. Cell size value: %lf", self.cellSize);
}
要更改单元格大小:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath {
if(indexPath.row == self.selectedRowIndex) {
NSLog(@"Resizing cell with size: %lf", self.cellSize);
return self.cellSize + 10;
}
return 44;
}
输出结果如下:
2015-02-24 22:59:08.902 testProject[62200:2703641] Resizing cell with size: 0.000000
2015-02-24 22:59:09.064 testProject[62200:2703641] Calling webViewDidFinishLoad. Cell size value: 501.000000
有没有办法只在 webViewDidFinishLoad
执行后调整单元格的大小?
非常感谢任何帮助!!
我很好奇这是否与您做事的顺序有关。你能尝试这样做吗:
[cell addSubview:self.webView];
self.webView.frame = ... create frame with cell width and height set to 1 ...
[self.webView loadHTMLString:finalString baseURL:nil];
我仍然不知道为什么会这样,但我使用以下方法解决了它:
我将 [tableView beginUpdates]
和 [tableView endUpdates]
指令移至 webViewDidFinishLoad
方法。这样,每当执行 webViewDidFinishLoad
时,它都会正确更新单元格大小。虽然我认为这不是最好的解决方案,但它确实有效。
现在,我的 webViewDidFinishLoad
方法如下所示:
- (void) webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
frame.size.height = 1;
aWebView.frame = frame;
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
self.cellSize = fittingSize.height;
[self.tableView beginUpdates];
[self.tableView endUpdates];
NSLog(@"Calling webViewDidFinishLoad. Cell size value: %lf", self.cellSize);
}
也许答案可以帮助遇到类似问题的其他人。
我的工作解决方案是使用 KVO。小心移除观察者。在 didEndDisplayingCell
或 viewWillDisappear
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.webview.addObserver(self, forKeyPath: "scrollView.contentSize", options: NSKeyValueObservingOptions.New, context: &context)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String: AnyObject]?, context: UnsafeMutablePointer<Void>) {
if let webview = object as? UIWebView {
let cs = webview.scrollView.contentSize
}
}
防止死循环。关键是如果你已经得到了 webview 的高度,只需 return 在 webViewDidFinishLoad 方法中。我的 webViewDidFinishLoad 看起来像这样:
// If the height is already exist, just return to prevent the infinite loop
// The default height is 0.0
if ([[self.webviewHeightDic objectForKey:[NSString stringWithFormat:@"%ld",(long)webView.tag]] floatValue] != 0.0) {
return;
}
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
NSLog(@"Cell height = %f ",fittingSize.height);
// Set the height to the target webview
[self.webviewHeightDic setObject:[NSNumber numberWithFloat:fittingSize.height]
forKey:[NSString stringWithFormat:@"%ld",(long)webView.tag]];
// Refresh the tableView
[self reloadData];