-
why
在日常开发过程中,有时候会遇到需要在app中嵌入网页,此时使用WebView实现效果,但在默认情况下是无法点击图片查看大图的,更无法保存图片。本文将就这一系列问题的实现进行说明。
这里面主要还是用到了android原生和js交互的知识、js添加事件的知识。
1、首先在andorid的页面中获取到html的字符串(bean.getContent()),然后在调用公共方法去获取到网页中的所有图片数组集合。之后就是android原生与js交互的规则了,如你所见,此处不再详细介绍。
//这两行copy出来,这个变量是WebView设置和js交互时设置的名称,可以随意起,js调用的时候也用这个就可以了
public static final String JSCALLJAVA= "jsCallJavaObj";
private String method = CommonUtil.JSCALLJAVA;
String[] imgs = JqStrUtil.returnImageUrlsFromHtml(bean.getContent());
web_course.addJavascriptInterface(new ImageJavascriptInterface(this,imgs), method);
web_course.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
CommonUtil.setWebImageClick(view,method);
}
});
获取图片数组的方法,通过正则匹配来获取:
public static String [] returnImageUrlsFromHtml(String htmlCode) {
List<String> imageSrcList = new ArrayList<String>();
Pattern p = Pattern.compile("<img\\b[^>]*\\bsrc\\b\\s*=\\s*('|\")?([^'\"\n\r\f>]+(\\.jpg|\\.bmp|\\.eps|\\.gif|\\.mif|\\.miff|\\.png|\\.tif|\\.tiff|\\.svg|\\.wmf|\\.jpe|\\.jpeg|\\.dib|\\.ico|\\.tga|\\.cut|\\.pic|\\b)\\b)[^>]*>", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(htmlCode);
String quote = null;
String src = null;
while (m.find()) {
quote = m.group(1);
src = (quote == null || quote.trim().length() == 0) ? m.group(2).split("//s+")[0] : m.group(2);
imageSrcList.add(src);
}
if (imageSrcList.size() == 0) {
return null;
}
return imageSrcList.toArray(new String[imageSrcList.size()]);
}
接下来是android原生和js交互的代码:
(1) Java类,js会通过之前设置的名称method来调用到其中的方法
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
/**
* WebView与android交互的接口设置实现类
* 1、可接口然后具体实现,然后在webview设置时具体实现
* 2、也可以直接实现,这样在同样需求的地方就可以直接复用了
* Created by dl on 2018/8/9.
*/
public class ImageJavascriptInterface {
private Context context;
private String[] imageUrls;
public ImageJavascriptInterface(Context context, String[] imageUrls) {
this.context = context;
this.imageUrls = imageUrls;
}
//java回调js代码,不要忘了@JavascriptInterface这个注解,不然点击事件不起作用
@JavascriptInterface
public void openImage(String img,int pos) {
Intent intent = new Intent(context, PreviewImgActivity.class);//改为你要跳转的页面
//具体要传递的参数自行传递即可
intent.putExtra("currentItem",String.valueOf(pos));
Bundle bundle = new Bundle();
bundle.putStringArray("imgUrls",imageUrls);
intent.putExtras(bundle);
context.startActivity(intent);
}
}
(2)
这段代码是在onPageFinished网页加载完成之后设置的,其中主要是添加了一段js代码,只有在网页加载完成之后,才能从dom中获取所有的img节点也就是图片。至于本身前端写的html中并没有给img添加点击的事件,所以我们来动态给他添加进去。
一般h5和原生交互,这段代码可以直接h5来写,你将你设置的java方法和起的名字告诉h5让其写进去就可以(具体到下面代码中就是method和openImage方法)
/**
* 设置网页中图片的点击事件
* @param view
*
*/
public static void setWebImageClick(WebView view,String method) {
String jsCode="javascript:(function(){" +
"var imgs=document.getElementsByTagName(\"img\");" +
"for(var i=0;i<imgs.length;i++){" +
"imgs[i].pos = i;"+
"imgs[i].onclick=function(){" +
"window."+method+".openImage(this.src,this.pos);" +
"}}})()";
view.loadUrl(jsCode);
}
上面代码还需要一点说明:就是传递当前图片的位置问题,直接传i是不行的,好像有什么闭包的问题,我查询的时候也有一个网友对此作了很详细的说明和解决方案的提供,传送门,我们这里采用的是给他设置一个属性来解决
这里我最初想通过这里把图片也赋值给一个属性,然后将图片数组传到java的方法参数中,但是无论是用了闭包还是设置属性,java那边总是接受不到,这个疑问我至今不解,所以有知道的小伙伴儿还请不吝赐教,感激不尽啊。
网友评论