开发者

UITableViewCell holding a UIWebViewCell with Dynamic Height and a Loading Animation

开发者 https://www.devze.com 2023-03-14 10:14 出处:网络
I am currently trying to nest a UIWebView (among othe开发者_运维知识库r elements) into a custom UITableViewCell subclass.

I am currently trying to nest a UIWebView (among othe开发者_运维知识库r elements) into a custom UITableViewCell subclass.

I need to dynamically determine the size of the cell (using heightForRowAtIndexPath) but for some reason when I do it like so, the height always gets printed as 0:

UIWebView* wv = [[[UIWebView alloc] init] autorelease];
[wv loadHTMLString:body baseURL:nil];
[wv setNeedsLayout]; //I don't think these are necessary but I tried anyway.
[wv setNeedsDisplay];
CGSize wvSize = [wv sizeThatFits:webViewBounds]; 
NSLog(@"WVHEIGHT %f", wvSize.height); //THIS IS WHERE IT PRINTS.
CGFloat retVal = 10.0f;
retVal += 50 > wvSize.height ? 50 : wvSize.height;
retVal += 2 + 15 + 10;

return retVal;

Now, if I do that exact same calculation using the cell.webView that I have access to in cellForRowAtIndexPath, it returns a non-zero value. However, I'd really like to avoid loading an entire cell just to figure out how tall it should be...

Additionally, UIWebView is very slow at rendering text (and it is unfortunately not negotiable that I use UIWebView), so I was wondering if there's a way to tell it to display the typical Apple "rotating gear" activity icon until it has its text fully loaded and ready to render.


I would recommend hiding each UIWebView until it is done loading, and showing a loading indicator instead. I would then make a dictionary with keys that match the tags, and for each entry in the dictionary, I would store the size of the UIWebView.

Make your controller conform to the UIWebViewDelegate protocol, and use the following code:

- (void)webViewDidFinishLoad:(UIWebView *)webView {

    NSString *output = [webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('this').offsetHeight;"];

    [self.webViewHeights setValue:[output floatValue] forKey:[NSString stringWithFormat:@"%f", webView.tag]];

}

After that, add code to hide your loading view and display your UIWebView, then call a table reload. In your cell height method, just check the correct array element for your UIWebView height.

Edit:

It seems I left out the important part!

OK, so, to create non-visible UIWebViews, you just need to create them, but not actually add them to a view. For example, you could do something like this in your viewDidLoad method:

UIWebView *newWebView = [[UIWebView alloc] initWithFrame:newFrame];
[newWebView loadHTMLString:body baseURL:nil];
newWebView.tag = 1;

[self.webViewDictionary setObject:newWebView forKey:@"1"];

Then in your table code, say something like

NSString *tagString = [NSString stringWithFormat:@"%d", indexPath.row];
UIWebView *curWebView = [self.webViewDictionary objectForKey:tagString];

if (curWebView.loading == NO) {

    CGRect newFrame = curWebView.frame;
    newFrame.size.height = [self.webViewHeights objectForKey:tagString];
    curWebView.frame = newFrame;

    [cell addSubview:curWebView];

} else {

    UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorStyleGray];

    [cell addSubview:activityIndicator];

}


I don't think sizeThatFits: is what you want to use.

sizeThatFits:

Asks the view to calculate and return the size that best fits its subviews.

Your webview does not have any subviews, only HTML.

UIWebView has no init method of its own, so you probably should use initWithFrame: (from the UIView superclass) to set the size directly. You can set it to the size you want, which is the size of the tableView cell in this case.

0

精彩评论

暂无评论...
验证码 换一张
取 消