ios·WKWebView\UIWebView加载HTMLString,实现图片懒加载

背景:
项目中开发商品类型数据,数据可变性较大,所以商品详情数据存在文案和图片富文本显示,后台返回了html格式的数据供前端展示。
如果用webView直接显示的话,需要等html内容完全展示才能获取webView需要展示的高度。但是我们需要做到的是,先展示文字和在有图片的地方展示占位图,等待图片加载完成再显示出图片。
场景:将WKWebView放在TableView的cell中进行展示,就需要计算内容的展示高度以刷新cell的高度。
实现思路:拿到后台返回的html字符串 - 加入jquery.js - 将拿到的html嵌入到自己创建的html内容 - loadWebViewWithHtmlString

文中使用到的懒加载jquery.js以及html下载地址: https://github.com/heqican/WebViewLazyLoadImage.git

上代码:
从服务端拿到的html如下:

<img src="https://img01.luckincoffeecdn.com/group1/M00/00/06/CmicNV0ui1GABf-SAAGQDLX5qe8931.jpg" alt="" /><br />
<ul class="attributes-list" style="font-family:tahoma, arial, " background-color:#ffffff;"="">
<li style="text-indent:5px;">
    品牌:&nbsp;鼠绘动漫
</li>
<li style="text-indent:5px;">
    型号:&nbsp;碗
</li>
<li style="text-indent:5px;">
    适用年龄:&nbsp;14周岁以上
</li>
<li style="text-indent:5px;">
    周边产品:&nbsp;碗碟
</li>
<li style="text-indent:5px;">
    出售状态:&nbsp;现货
</li>
<li style="text-indent:5px;">
    动漫地区:&nbsp;日本
</li>
<li style="text-indent:5px;">
    大小:&nbsp;现货 微瑕
</li>
<li style="text-indent:5px;">
    ACG作品名:&nbsp;海贼王/onepiece
</li>
<li style="text-indent:5px;">
    ACG角色名:&nbsp;路
</li>
    </ul>
<img src="https://img01.luckincoffeecdn.com/group1/M00/00/06/CmicNF0ui1GAB_dJAAD_t8ZZpH0581.jpg" alt="" /><img src="https://img01.luckincoffeecdn.com/group1/M00/00/06/CmicNV0ui1GAB1YTAAL7Y3yui30725.jpg" alt="" /><img src="https://img01.luckincoffeecdn.com/group1/M00/00/06/CmicNF0ui1KANKycAAHmOHfWUJU987.jpg" alt="" /><br />
<img src="https://img01.luckincoffeecdn.com/group1/M00/00/06/CmicNV0ui1KALE3pAAKuN6sXwik137.png" alt="" />

如果直接显示上面的html加载图片过程需要等待很长时间,才能加载出页面内容。

开始懒加载处理:
1、将上方下载的懒加载包,导入工程中:


image.png

2、在加载HTMLString前,先组装html数据,让html具有懒加载功能:

///实现html图片懒加载
- (void)lazyloadHTMLImagesWithHTMLString:(NSString *)htmlString complete:(void(^)(NSString *tempHtml, NSURL *baseURL))complete{
    //替换标签
    NSString *originalStr = [htmlString stringByReplacingOccurrencesOfString:@"src" withString:@"data-original"];
    //获取temp文件的路径
    NSString *tempPath = [[NSBundle mainBundle]pathForResource:@"temp" ofType:@"html"];
    //加载temp内容为字符串
    NSString *tempHtml = [NSString stringWithContentsOfFile:tempPath encoding:NSUTF8StringEncoding error:nil];
    //替换temp内的占位符{{Content_holder}}为需要加载的HTML代码
    tempHtml = [tempHtml stringByReplacingOccurrencesOfString:@"{{Content_holder}}" withString:originalStr];
    //LazyloadImage目录下的js文件在根路径,因此需要在加载HTMLString时指定根路径
    NSString *basePath = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:basePath];
    
    if (complete) {
        complete(tempHtml,baseURL);
    }
}

3、组装好新的html之后,开始加载html内容:

///图片懒加载处理
        [self lazyloadHTMLImagesWithHTMLString:model.htmlDesc complete:^(NSString *tempHtml, NSURL *baseURL) {
            //加载html
            [self.webView loadHTMLString:tempHtml baseURL:baseURL];
            //添加观察者
            [self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
        }];

4、给webview添加观察者,监听图片加载情况。等待图片加载完成,重新计算@"document.body.offsetHeight"高度,刷新展示控件的高度

#pragma mark - 观察者监听
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    if([keyPath isEqualToString:@"contentSize"]) {//由于图片在实时加载,监听到内容高度变化,需要实时刷新您的控件展示高度 等
        //设置展示元素样式
        [self setWebViewFontStyle];
        //刷新控件高度
        [self refreshWebViewHeight:self.webView];
    }
}
#pragma mark - webview加载 delegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    self.isLoaded = YES;
    [self refreshWebViewHeight:webView];
}

//计算webView渲染高度并刷新视图
- (void)refreshWebViewHeight:(WKWebView *)webView{
    [webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result,NSError * _Nullable error){
        CGFloat height = [result floatValue] + 20;//这里+20
        [self.webView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(5);
            make.left.mas_equalTo(self.mas_left).offset(Interval_Size_8);
            make.right.mas_equalTo(self.mas_right).offset(-Interval_Size_8);
            make.height.mas_equalTo(@(height));
        }];
        
        if (self.contentHeight != height+1) {
            self.contentHeight = height+1;
            if (self.contentHeight > 0) {
                if (self.loadedBlock) {
                    //这里获取到高度之后,根据具体逻辑进行处理
                    self.loadedBlock(self.contentHeight);//高度确定了,回调刷新详情页高度和tableView
                }
            }
        }
    }];
}

这样就可以实现加载HTMLString 先展示文字和占位符,图片等待加载完成再展示了。

懒加载效果:
未加入懒加载之前,等待webview加载需要耗时太久了,体验效果极差。
加入懒加载后就能完美加载富文本的html啦,管它图片有多大,管它网速有多慢~~
效果:

图片加载中.PNG

图片加载完成.PNG

其他:
可以往html中注入JS,修改展示样式等等:

//设置webView 样式
- (void)setWebViewFontStyle{
    //字体颜色
    [self.webView evaluateJavaScript:@"document.getElementsByTagName('body')[0].style.webkitTextFillColor= '#666666'" completionHandler:nil];
    //修改字体大小
    [self.webView evaluateJavaScript:@"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '90%'"completionHandler:nil];
    //禁止用户选择
    [self.webView evaluateJavaScript:@"document.documentElement.style.webkitUserSelect='none';" completionHandler:nil];
    [self.webView evaluateJavaScript:@"document.activeElement.blur();" completionHandler:nil];
    // 改变网页内容背景颜色
//    [self.webView evaluateJavaScript:@"document.body.style.backgroundColor=\"#616465\"" completionHandler:nil];
}

//处理WKWebView 图片展示超出边界问题
- (void)processingBeyondTheBorder{
    NSString *js = @"function imgAutoFit() { \
    var imgs = document.getElementsByTagName('img'); \
    for (var i = 0; i < imgs.length; ++i) {\
    var img = imgs[i];   \
    img.style.maxWidth = %f;   \
    } \
    }";
    js = [NSString stringWithFormat:js, [UIScreen mainScreen].bounds.size.width-Interval_Size_8*2];
    //注入JS
    [self.webView evaluateJavaScript:js completionHandler:nil];
    [self.webView evaluateJavaScript:@"imgAutoFit()" completionHandler:nil];
}

//禁止缩放
- (void)setWebViewUserUnScalable{
    NSString *js = @"var script = document.createElement('meta');"
    "script.name = 'viewport';"
    "script.content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0, user-scalable=no\";"
    "document.getElementsByTagName('head')[0].appendChild(script);";
    //注入JS
    [self.webView evaluateJavaScript:js completionHandler:nil];
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342