程序员

IOS显示(适配)HTML文本

2018-09-07  本文已影响28人  请输入昵称Arthas

针对HTML字符串,可以用UIKit框架中的UILabel 、UITextView。
WebKit中的UIWebView、WKWebView都可以显示HTML字符。

先分别看一下实现方法。

UILabel 、UITextView

NSString *html = @"<span style=\"font-size: 18px;\">看到了没有?</span><br/><p><img width='100%%' height='auto' src=\"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1536307082986&di=71ee1725f4519c99a5714b36206f2d3a&imgtype=0&src=http%3A%2F%2Fimg.juimg.com%2Ftuku%2Fyulantu%2F120414%2F2980-120414155H918.jpg\" title=\"\" alt=\"4da9754bd21cd8318ddaa20032a77a92.jpg\"/>内容3</p><br/><span style=\"font-size: 18px;\"> 没事</span><br/>有有有<br/>";

//这个是UILabel
NSAttributedString *attri = [[NSAttributedString alloc]initWithData:[html dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];

self.titleLabel.attributedText = attri;

//这个是UITextView
NSAttributedString *attri = [[NSAttributedString alloc]initWithData:[html dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
self.textView.attributedText = attri;

从上面的方法大家都可以看到UILabel、UITextView它们都有一个属性attributedText。
而NSAttributedString中的可选NSDocumentTypeDocumentAttribute它可以绘制4种文本格式。
先看一下官方的定义。

// Supported document types for the NSDocumentTypeDocumentAttribute key in the document attributes dictionary.
//普通文本
UIKIT_EXTERN NSAttributedStringDocumentType const NSPlainTextDocumentType NS_AVAILABLE(10_0, 7_0);
//富文本
UIKIT_EXTERN NSAttributedStringDocumentType const NSRTFTextDocumentType  NS_AVAILABLE(10_0, 7_0);
//带附件的富文本
UIKIT_EXTERN NSAttributedStringDocumentType const NSRTFDTextDocumentType NS_AVAILABLE(10_0, 7_0);
//可以加载HTML格式的文本
UIKIT_EXTERN NSAttributedStringDocumentType const NSHTMLTextDocumentType  NS_AVAILABLE(10_0, 7_0);

这里要特别注意一下,titleLabel.attributedText 与 titleLabel.text 差不多一个意思。所以其他所有属性还是归UI组件本身控制的。例如UILabel中的numberOfLines是控制显示行数的,如果你发现只绘制了一行,写上以下方法就可以了。

self.titleLabel.numberOfLines = 0;

现在大家把代码贴上去运行一下会发现,图片怎么会显示不完???


图片显示不完.jpeg
NSString *html = @"<span style=\"font-size: 18px;\">看到了没有?</span><br/><p><img width='100%%' height='auto' src=\"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1536307082986&di=71ee1725f4519c99a5714b36206f2d3a&imgtype=0&src=http%3A%2F%2Fimg.juimg.com%2Ftuku%2Fyulantu%2F120414%2F2980-120414155H918.jpg\" title=\"\" alt=\"4da9754bd21cd8318ddaa20032a77a92.jpg\"/>内容3</p><br/><span style=\"font-size: 18px;\"> 没事</span><br/>有有有<br/>";

重点来了,大家可以看到上面的HTML。它的最外层是没有明确宽度是多少的,大家学过一点网页的都知道,一个页面它起码也是要有<html><head><body>等标签的。
图片那里宽度是width='100%%' ,但是最外层是多大?并没有明确指定,这里就会按照原图大小显示。所以我们就要把这段HTML代码给补全了。

/**
 适配HTML Body宽度为指定大小
 @param width 宽度
 @return result
 */
- (NSString *)htmlAddbodyWidth:(CGFloat)width html:(NSString*)html{
    NSString *tempHtml = [NSString stringWithFormat:@"<html><head></head><body style=\"width:%f;height: auto;\">"
                      "%@"
                      "</body></html>",width,html];
    return tempHtml;
}

重新写一下完整的例子

NSAttributedString *attri = [[NSAttributedString alloc]initWithData:[[self htmlAddbodyWidth:[UIScreen mainScreen].bounds.size.width-56 html:html] dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];

self.titleLabel.attributedText  = attri;

这样就可以完整的显示了


图片显示完整.jpeg

再提供多一种选择吧,直接去修改图片的样式的方法,也可以提取HTML图片中的路径。下面的方法我是写在NSString的装饰类中的,需要的自己修改一下就可以了。

/**
 过滤HTML字符串中的图片指定宽度
 
 @param width 宽度
 @return result
 */
- (NSString *)htmlWebAutoImageSizeWidth:(CGFloat)width{
    if (self == nil || self.length == 0) {
        return @"";
    }
    NSString *content = [self stringByReplacingOccurrencesOfString:@"&amp;quot" withString:@"'"];
    content = [content stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
    content = [content stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
    content = [content stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""];
    
    
    NSString *html = content;
    NSString * regExpStr = @"<(img|IMG)[^\\<\\>]*>";
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regExpStr options:NSRegularExpressionCaseInsensitive error:nil];
    
    NSArray *matches = [regex matchesInString:html
                                    options:0
                                      range:NSMakeRange(0, [html length])];
    
    
    //HTML中的<img ...... />数组
    NSMutableArray *imgArray = [NSMutableArray array];
    //<img src="URL"/>中的URL数组
    NSMutableArray *urlArray = [NSMutableArray array];
    
    for (NSTextCheckingResult *result in matches) {
        NSRange range   = result.range;
        NSString *group = [html substringWithRange:range];
        NSRange srange1 = [group rangeOfString:@"http"];
        NSString *tempString1 = [group substringWithRange:NSMakeRange(srange1.location, group.length - srange1.location)];
        NSRange srange2 = [tempString1 rangeOfString:@"\""];
        NSString *tempString2 = [tempString1 substringWithRange:NSMakeRange(0,srange2.location)];
        [urlArray addObject:tempString2];
        [imgArray addObject:group];
    }
    
    for (int i = 0; i < imgArray.count; i++) {
        NSString *string = imgArray[i];
        html = [html stringByReplacingOccurrencesOfString:string withString:[NSString stringWithFormat:@"<img src=\"%@\" title=\"\" alt=\"%lld\" width=\"%f\" height=\"auto\">",urlArray[i],[NSDate timeStamp]+i,width]];
    }
    
    
    return html;
}

再来看一下WebView是如何显示的呢?
UIWebView、WKWebView的实现方法。

NSString *html = @"<span style=\"font-size: 18px;\">看到了没有?</span><br/><p><img width='100%%' height='auto' src=\"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1536307082986&di=71ee1725f4519c99a5714b36206f2d3a&imgtype=0&src=http%3A%2F%2Fimg.juimg.com%2Ftuku%2Fyulantu%2F120414%2F2980-120414155H918.jpg\" title=\"\" alt=\"4da9754bd21cd8318ddaa20032a77a92.jpg\"/>内容3</p><br/><span style=\"font-size: 18px;\"> 没事</span><br/>有有有<br/>";
[_webView loadHTMLString:html baseURL:nil];

同理,如果图片显示不完一样要补全HTML!!!

那在实际项目中用那一种实现方法好呢?下面就来总结分析一下。
总结:
1、如果只是显示文本并不会有与用户交与的操作,建议是用UILabel、UITextView去显示HTML文本。因为这样系统可以很流畅的渲染UI,并不会卡顿。特别是在UITableView中的Cell自适应高度显示。
2、如果涉及到点击图片要求放大显示、其他交互等,那就用WKWebView。WKWebView它渲染UI的时间比较长,体验不怎么好,就相当于打开一个网页那样,是要等待的。并且呢在cell中做自适应显示难度是比较高的。(我有几个思路,但并没有实现过)。

上一篇 下一篇

猜你喜欢

热点阅读