需求如下:
【生效時間】和【辦理號碼】的高度可以計算后频。
【圖文介紹】返回的是一串 HTML 代碼沼撕,類似 "<span style="font-size:14px;color:#000000;">\U3010\U8d44\U8d39\U6807\U51c6\U3011</span><br />" 這樣的代碼遭顶。
加載 HTML 代碼,可用 UILabel 或者 UIWebView牛柒,難點在于對高度的計算堪簿。
UILabel 加載 HTML
label 加載 HTML 的原理是把HTML轉(zhuǎn)成富文本,在賦值給
label.attributedText
HTML 轉(zhuǎn)富文本的代碼如下:
NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding) };
// htmlString 為需加載的HTML代碼
NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding];
_label.attributedText = [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil];
此時可計算出文本高度皮壁,代碼如下:
CGFloat attriHeight = [_label.attributedText boundingRectWithSize:CGSizeMake(SCREEN_WIDTH - 30*layoutBy6(), CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size.height;
可用類方法返回Cell的高度
// cell的高度
+(CGFloat)getCellHeight:(NSString*)htmlStr {
NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding)
};
NSData *data = [htmlStr dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil];
CGFloat attriHeight = [attrStr boundingRectWithSize:CGSizeMake([UIScreen mainScreen].bounds.size.width - 30, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size.height;
return attriHeight ;
}
加載出來的效果如下:
UIWebView 加載 HTML
UIWebView 加載 HTML 的方法很簡單椭更,就一句代碼
[_webView loadHTMLString:desStr baseURL:nil];
但此時并不知道 webView 的高度,需要通過 UIWebViewDelegate 的代理方法獲取高度蛾魄。
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGFloat webViewHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
_webView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, webViewHeight);
}
由于高度必須在 webView 完成加載之后才能獲取得到虑瀑,當獲取到高度之后湿滓,需要通知 tableView reloadData。然而舌狗,tableView 刷新會對該 Cell 重新賦值叽奥,Cell 賦值導致 webView 又完成一遍加載。痛侍。朝氓。程序陷入了死循環(huán)。
避免該情況主届,對需要加載的內(nèi)容提前賦值給 Cell赵哲。不要在tableview cellForRowAtIndexPath 方法里賦值,網(wǎng)絡(luò)請求回來后就賦值君丁。把 webViewCell 懶加載枫夺,Block 里面執(zhí)行 tableView section 更新。
Cell 的代碼如下??
@interface WebViewCell : UITableViewCell
<UIWebViewDelegate>
@property (nonatomic , copy) NSString *webContentStr;
@property (nonatomic , assign) CGFloat cellHeight;
@property (nonatomic, copy) void(^Block)(void); // Block回調(diào)
@end
@implementation WebViewCell
#pragma mark setter
-(void)setWebContentStr:(NSString *)webContentStr {
_webContentStr = webContentStr;
// 移除所有視圖
[self.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
// 創(chuàng)建 WebView 谈截,webView 須給初始值筷屡,在 delegate 再更改 frame
UIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 1)];
webView.scrollView.scrollEnabled = NO;
webView.delegate =self;
[webView sizeToFit];
[self.contentView addSubview:webView];
//加載Html文件
[webView loadHTMLString:desStr baseURL:nil];
}
#pragma mark UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
//加載完成后獲取WebView實際高度
CGFloat webViewHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
webView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, webViewHeight);
self.cellHeight = webViewHeight;
if (self.Block) {
self.Block();
}
}
@end
VC 部分的代碼??
@property (nonatomic, strong) WebViewCell *webCell涧偷;
#pragma mark net request
- (void)gainWebContent {
self.webCell.webContentStr = 網(wǎng)絡(luò)請求回來的數(shù)據(jù)簸喂;
}
#pragma mark tableView
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return self.webCell.cellHeight;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 2) {
return self.webCell;
}
}
#pragma mark lazy load
- (WebCell *)webCell{
if (!_webCell) {
NSString *cellIdentifier = @"webCell";
_webCell = [[WebCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
//回調(diào)刷新Cell內(nèi)容及高度
__weak typeof(self) weakSelf = self;
_webCell.Block = ^{
__strong typeof(self) strongSelf = weakSelf;
[strongSelf.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationNone];
};
}
return _webCell;
}
題外話
@"document.body.scrollHeight" 中的 scrollHeight。有的資料里面燎潮,這里的語句是 @"document.body.offsetHeight"喻鳄。稍微查了一下 offsetHeight 和 scrollHeight 的區(qū)別:
1)document.documentElement.scrollHeight = document.documentElement.offsetHeight => 就是整個網(wǎng)頁文檔body的高度,隨著網(wǎng)頁內(nèi)容的多少變化确封,包括網(wǎng)頁內(nèi)的所有border,margin,padding除呵;
2)body.clientHeight = body.offsetHeight => body的內(nèi)容高度,不包括margin和border值爪喘,實際上就是body的height值颜曾;
3)body.scrollHeight => 包括body的margin,body值
a 當網(wǎng)頁內(nèi)容超出瀏覽器可視窗口高度值時秉剑,= body.clientHeight+margin+border = document.documentElement.scrollHeight ;
b 當網(wǎng)頁內(nèi)容較少未超出時泛豪,= document.documentElement.clientHeigh 也就是瀏覽器窗口高度值(這是它的最小值);