如何捕获WebView加载的HTML中特定div节点的内容?
捕获WebView中特定Div的内容截图
要实现只截取WebView中指定Div的内容,核心思路是先通过JavaScript获取目标Div在页面中的位置和尺寸,再对整页截图进行裁剪,具体步骤如下:
1. 启用JavaScript并获取Div的位置与尺寸
首先确保WebView开启JS支持,然后在页面加载完成后,注入JS代码获取目标Div的坐标和大小:
// 初始化WebView时启用JS webView.settings.javaScriptEnabled = true // 存储目标Div的位置与尺寸参数 var divTop = 0 var divLeft = 0 var divWidth = 0 var divHeight = 0 webView.webViewClient = object : WebViewClient() { override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) // 替换成你的目标Div选择器(比如id、class) val targetSelector = "document.getElementById('targetDiv')" webView.evaluateJavascript( """ var div = $targetSelector; if(div) { var rect = div.getBoundingClientRect(); var scrollTop = window.pageYOffset || document.documentElement.scrollTop; var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; // 适配屏幕像素密度,避免裁剪偏移 var scale = window.devicePixelRatio; JSON.stringify({ top: Math.round((rect.top + scrollTop) * scale), left: Math.round((rect.left + scrollLeft) * scale), width: Math.round(rect.width * scale), height: Math.round(rect.height * scale) }) } else { null } """.trimIndent() ) { result -> if (result != "null") { try { val jsonObject = JSONObject(result) divTop = jsonObject.getInt("top") divLeft = jsonObject.getInt("left") divWidth = jsonObject.getInt("width") divHeight = jsonObject.getInt("height") } catch (e: JSONException) { e.printStackTrace() } } } } }
说明:
- 将
targetDiv替换为你要截取的Div的实际ID,若用class选择器则改为document.querySelector('.your-class-name') - 加入
devicePixelRatio是为了适配不同屏幕的像素密度,保证裁剪区域精准
2. 裁剪整页截图得到目标Div区域
基于你现有的整页截图逻辑,对获取到的Bitmap进行裁剪,只保留目标Div的区域:
screenButton.setOnClickListener { // 校验Div参数是否有效 if (divWidth <= 0 || divHeight <= 0) { Toast.makeText(this, "未找到目标Div", Toast.LENGTH_SHORT).show() return@setOnClickListener } val baos = ByteArrayOutputStream() val randomID = Random().nextInt() // 获取整页截图 val fullPageBitmap = getBitmapFromView(scrollView, scrollView.getChildAt(0).height, scrollView.getChildAt(0).width) // 处理裁剪边界,避免超出Bitmap范围 val cropLeft = divLeft.coerceAtLeast(0) val cropTop = divTop.coerceAtLeast(0) val cropWidth = divWidth.coerceAtMost(fullPageBitmap.width - cropLeft) val cropHeight = divHeight.coerceAtMost(fullPageBitmap.height - cropTop) if (cropWidth <= 0 || cropHeight <= 0) { Toast.makeText(this, "裁剪区域无效", Toast.LENGTH_SHORT).show() fullPageBitmap.recycle() return@setOnClickListener } // 裁剪出目标Div的Bitmap val targetBitmap = Bitmap.createBitmap(fullPageBitmap, cropLeft, cropTop, cropWidth, cropHeight) fullPageBitmap.recycle() // 释放整页截图内存 // 保存裁剪后的图片(原有逻辑不变,替换为targetBitmap) val externalStoragePublicDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) val imageFile = File(externalStoragePublicDirectory, "Screenshot$randomID.png") FileOutputStream(imageFile).use { targetBitmap.compress(Bitmap.CompressFormat.PNG, 70, it) } // Base64编码逻辑 targetBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos) val imageBytes: ByteArray = baos.toByteArray() val imageString: String = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Base64.getEncoder().encodeToString(imageBytes) } else { android.util.Base64.encodeToString(imageBytes, android.util.Base64.DEFAULT) } println("Base64 Encoding : $imageString") targetBitmap.recycle() // 释放裁剪后的Bitmap内存 } // 你的getBitmapFromView函数(确保能正确获取整页截图) private fun getBitmapFromView(view: View, height: Int, width: Int): Bitmap { val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) val bgDrawable = view.background if (bgDrawable != null) { bgDrawable.draw(canvas) } else { canvas.drawColor(Color.WHITE) } view.draw(canvas) return bitmap }
关键注意事项
- 若目标Div是动态生成的(比如通过AJAX加载),需等待DOM完全渲染后再执行JS获取参数,可改用
window.onload或MutationObserver监听 - 注意内存回收:及时调用
recycle()释放不再使用的Bitmap,避免内存溢出 - 若WebView设置了缩放,需确保JS获取的坐标与Bitmap的像素比例一致
内容的提问来源于stack exchange,提问作者YannAsh
相关产品推荐
相关产品推荐

