需求描述:使用WebView加载一个链接,实现有图、无图模式之间的切换
- 阻塞图片的加载,网页上图片以一种灰底的形式存在
- 完全实现图片的隐藏
1. 阻塞图片的加载
这个就比较简单了,WebView本身提供了api,这种方式一般也会作为优化网页显示速率的一种方式
// 阻塞图片加载
wvWeb.settings.blockNetworkImage = true
2. 完全实现图片的隐藏
WebView本身并没有提供相关的方法,只能另寻出路,我们知道网页是以html语言编写的,我们只要拿到了网页源码,别说是图片隐藏了,简直可以为所欲为,既然方案出来了,就不要只限于想,一定要动手去淦。
在这里提供两种获取网页源码的方式
- 通过WebView加载一段js代码的方式获取
- 直接请求链接,下载其源码
2.1 通过WebView加载一段js代码的方式获取
直接上码
dataBinding.wvWeb.addJavascriptInterface(InJavaScriptLocalObj(), "java_obj")
dataBinding.wvWeb.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
view?.loadUrl(request?.url.toString())
return true
}
// 拦截当前链接内所有请求,其实在这个方式也可以实现 阻塞图片的加载
// 问题是无法根据一个统一的规则去判断这个链接是否是图片(如果是加载的公司自己的h5,完全可以制定这种规则)
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
Log.i(TAG, "shouldInterceptRequest: ${request?.url.toString()}")
if (request?.url.toString()是图片)
return WebResourceResponse(null, null, null)
else
return super.shouldInterceptRequest(view, request)
}
// 页面加载完成时的回调
override fun onPageFinished(view: WebView?, url: String?) {
view?.loadUrl("javascript:window.java_obj.getSource('<head>'+" +
"document.getElementsByTagName('html')[0].innerHTML+'</head>');")
super.onPageFinished(view, url)
}
}
inner class InJavaScriptLocalObj {
@JavascriptInterface
fun getSource(src: String?) {
Log.i(TAG, "source: $src")
}
}
2.2 直接请求链接,下载其源码
完全可以使用当时项目中的请求框架去下载网页源码,这里使用的是jsoup 三方库,这个库不仅可以获取源码,还可以解析处理html,提供了一整套非常省力的api,总之是一个好库,对于我这种对前端技术不咋熟悉还是非常nice的,具体使用自行google吧。 当我们拿到了html文本,就可以随心所欲了。 但是在测试过程中,微信公众号中的链接需要特殊处理。代码中有解释,请看👇
// app >>> build.gradle中添加
implementation 'org.jsoup:jsoup:1.13.1'
/**
* 切换显示模式
* @param url 网页链接
* @param hideImg 是否隐藏图片 true 隐藏 false 显示
*/
private fun changeWvLoadMode(url: String, hideImg: Boolean) {
lifecycleScope.launch(Dispatchers.Main) {
dataBinding.btnSwitch.text = if (hideImg) "无图模式开启" else "无图模式关闭"
// 适配微信公众号的了解加载有图模式
// 原因:微信可能对公众号中的图片有保护机制,使用loadDataWithBaseUR()的方式加载图片加载不成功,需要使用loadUrl的方式
if (是微信公众号链接 && !hideImg) {
dataBinding.wvWeb.loadUrl(url)
return@launch
}
if (document == null) {
withContext(Dispatchers.IO) {
document = Jsoup.connect(url).timeout(3000).get()
}
}
// 这里拿到所有img标签,返回的是一个Elements对象
val imgTags = document?.getElementsByTag("img")
Log.i(TAG, "imgTags: ${imgTags}")
for (element in imgTags!!) {
// 适配个别网页中获取的图片链接不完整的问题
val src = element.attr("src")
if (!src.startsWith("http"))
element.attr("src", "https:$src")
// 适配PC端链接在手机端显示问题
element.attr("width", "100%")
element.attr("height", "100%")
// 添加or移除隐藏属性,实现有图or无图模式(隐藏属性好像还有其他的,可以和公司前端小姐姐深入交流一下)
if (hideImg)
element.attr("hidden", "hidden")
else
element.removeAttr("hidden")
}
dataBinding.wvWeb.loadDataWithBaseURL(null,document.toString(),"text/html","utf-8", null)
}
}
Ending… 如果各位大佬有更好的方法,还请评论区赐教。
|