前言
APP开发过程中有一个需求,即加载html,点击图片可以全屏浏览。这其中需要注意的是,html是富文本,其高度的确定是一个点,另外获取html中的图片URL,是另外一个点,第三个点便是图片浏览器的使用。解决好这三个点,这个需求便完整的解决了。
实现效果
使用的类库
- IMYWebView
- XLPhotoBrowser+CoderXL
- Masonry
IMYWebView是加载html的类库,可以无缝的从UIWebView和WKWebView之间进行切换;
XLPhotoBrowser+CoderXL是一个图片浏览器,可以很方便的显示一组图片;
Masonry是布局类库,旨在添加webview时,编写约束更方便。
实现
-
解决加载html的问题
(1)如果获取到的图片是使用http进行访问的,则需要配置工程info.plist,使APP可以加载http的链接。
(2)从服务器获取的html文本通常是一个片段,将其直接显示到webview中是不合适的,因此通常将其进行一下填充,即填充上必要的标签。
// 填充html
NSString* htmlStructureStr = @"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0,user-scalable=no\"><style>*{margin: 0;padding: 0;}body{font-size: 12pt;} img{width: 100%% !important}</style></head><body>%@</body></html>";
_htmlData = [NSString stringWithFormat: htmlStructureStr,
[htmlStr stringByReplacingOccurrencesOfString: @"<p><br/></p>"
withString: @""]];
(3)在webview加载完成后,对其高度进行调整,需要使用javascript来获取其高度。
- (void)webViewDidFinishLoad:(IMYWebView *)webView {
[webView evaluateJavaScript: @"document.documentElement.scrollHeight"
completionHandler:^(id object, NSError *error) {
CGFloat height = (CGFloat)[object integerValue];
if (!error) {
// mainSVHeightConstraint为UIScrollView的滚动view高度约束
self.mainSVHeightConstraint.constant = height + 16.0f;
}
}];
// ......
}
- 获取html中的图片url
(1)首先需要给图片添加点击事件(javascript)。
- (void)webViewDidFinishLoad:(IMYWebView *)webView {
// ......
[webView evaluateJavaScript: @"function assignImageClickAction(){var imgs=document.getElementsByTagName('img');var length=imgs.length;for(var i=0; i < length;i++){img=imgs[i];if(\"ad\" ==img.getAttribute(\"flag\")){var parent = this.parentNode;if(parent.nodeName.toLowerCase() != \"a\")return;}img.onclick=function(){window.location.href='image-preview:'+this.src}}}"
completionHandler: ^(id object, NSError *error) {
}];
[webView evaluateJavaScript: @"assignImageClickAction();"
completionHandler: ^(id object, NSError *error) {
}];
[self getImages];
}
(2)获取html中的图片URL,仍然使用js进行获取。
- (void)getImages {
[self.imageMutArr removeAllObjects];
[self nodeCountOfTag: @"img" withNodeCountCallback:^(NSInteger count) {
for (int i = 0; i < count; ++i) {
NSString* jsStr = [NSString stringWithFormat:
@"document.getElementsByTagName('img')[%d].src", i];
[self.webView evaluateJavaScript: jsStr
completionHandler:^(id object, NSError *error) {
if (!error) {
[self.imageMutArr addObject: (NSString*)object];
}
}];
}
}];
}
// 获取某个标签的结点数量
- (void)nodeCountOfTag: (NSString*)tag
withNodeCountCallback: (void(^) (NSInteger))callback {
NSString* jsStr = [NSString stringWithFormat:
@"document.getElementsByTagName('%@').length", tag];
[self.webView evaluateJavaScript: jsStr
completionHandler:^(id object, NSError *error) {
NSInteger count = error ? 0 : [object integerValue];
callback(count);
}];
}
- 点击图片进行全屏浏览
点击图片调用的是webview的回调方法,然后使用第三方库XLPhotoBrowser进行显示。
- (BOOL)webView:(IMYWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
if ([request.URL.scheme isEqualToString: @"about:blank"])
return YES;
else if ([request.URL.scheme isEqualToString: @"image-preview"]) {
NSString* imageUrlStr = [request.URL.absoluteString
substringFromIndex: 14];
if (self.imageMutArr.count != 0) {
NSUInteger index = [self.imageMutArr indexOfObject: imageUrlStr];
[XLPhotoBrowser showPhotoBrowserWithImages: self.imageMutArr
currentImageIndex: index];
}
}
return YES;
}
至此,这三个点便都解决了,比较麻烦的是javascript的编写以及block的编写,区分清楚即可。
结束语
本实现中的部分代码是参考简书作者若锦的一篇简书《iOS中加载HTML数据,并点击图片或链接进行相应的操作》编写的,由于其代码时日较长,一些API的使用已经deprecated,因此进行了重写以适配最新的iOS 12。目前代码通过编译,已托管至github。
https://github.com/njim3/IMYWebViewDemo/