美文网首页程序员
IOS显示(适配)HTML文本

IOS显示(适配)HTML文本

作者: 请输入昵称Arthas | 来源:发表于2018-09-07 13:54 被阅读28次

    针对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中做自适应显示难度是比较高的。(我有几个思路,但并没有实现过)。

    相关文章

      网友评论

      • 武城君:string 转 attributedString很耗时,有好的解决方案吗?
        请输入昵称Arthas:我试过,都很快了。其他解决方案我也不知道了。你有用Instruments中的Time Profiler测试过你的转换string 转 attributedString 函数吗?这个工具可以分析一段代码运行要多少时间的
      • yqb:解决了问题 ,感谢

      本文标题:IOS显示(适配)HTML文本

      本文链接:https://www.haomeiwen.com/subject/gaqcgftx.html