Android WebView真机无法渲染ChartJs位图(模拟器正常)
问题:WebView加载ChartJs截图真机显示全白,模拟器正常
在WebView中使用ChartJs生成图表时,真机上截图得到全白画面,但模拟器完全正常。已尝试以下操作但无效:
- AndroidManifest中设置
android:hardwareAccelerated="true" - App初始化调用
WebView.enableSlowWholeDocumentDraw() - 加载URL前开启
binding.wvContent.settings.javaScriptEnabled = true - 尝试两种截图代码(见下文)
将hardwareAccelerated设为false后问题解决,但希望找到其他不关闭全局硬件加速的方案。
尝试过的截图代码
代码1:
fun screenshot (webView:WebView):Bitmap?{ try { val bitmap = Bitmap.createBitmap(webView.width, webView.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) webView.draw(canvas) return bitmap } catch (e: Exception) { e.printStackTrace() } return null }
代码2:
fun screenShot(mWebView:WebView) { // measure the webview mWebView?.measure( View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED) ) //layout of webview mWebView?.layout(0, 0, mWebView!!.measuredWidth, mWebView!!.getMeasuredHeight()) mWebView?.isDrawingCacheEnabled = true mWebView?.buildDrawingCache(true)//create Bitmap if measured height and width >0 val bm = if (mWebView?.measuredWidth!! > 0 && mWebView?.measuredHeight!! > 0) { Bitmap.createBitmap( mWebView?.measuredWidth!!, mWebView?.measuredHeight!!, Bitmap.Config.ARGB_8888 ) } else null // Draw bitmap on canvas bm?.let { Canvas(bm).apply { drawBitmap(it, 0f, bm.height.toFloat(), Paint()) mWebView?.draw(this) } } }
可行替代方案
1. 仅对目标WebView禁用硬件加速
不全局关闭硬件加速,只给出现问题的WebView单独禁用:
binding.wvContent.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
建议在WebView初始化完成后调用,比如onViewCreated或WebView加载完成的回调中设置。
2. 等待ChartJs渲染完成后再截图
真机硬件加速下ChartJs渲染速度慢于模拟器,过早截图会导致画面未绘制完成。通过WebView的JS接口监听渲染完成事件:
步骤1:H5端监听ChartJs渲染事件
// 假设H5中Chart实例名为myChart,监听动画完成事件 myChart.on('animationComplete', function() { window.android.notifyChartReady(); });
注:部分ChartJs版本可能使用render事件替代animationComplete,需根据实际版本调整
步骤2:Android端定义JS接口并触发截图
class ChartJavascriptInterface(private val screenshotCallback: () -> Unit) { @JavascriptInterface fun notifyChartReady() { // 回到主线程执行截图 Handler(Looper.getMainLooper()).post { screenshotCallback.invoke() } } } // 给WebView添加JS接口 binding.wvContent.addJavascriptInterface( ChartJavascriptInterface { // 调用你的截图方法 val bitmap = screenshot(binding.wvContent) // 处理截图结果 }, "android" )
3. 使用WebView原生截图方法(API 21+)
尝试WebView原生的截图API,硬件加速下兼容性更好:
API 21-28:使用capturePicture
fun captureWebView(webView: WebView): Bitmap? { return try { val picture = webView.capturePicture() val bitmap = Bitmap.createBitmap(picture.width, picture.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) picture.draw(canvas) bitmap } catch (e: Exception) { e.printStackTrace() null } }
API 28+:使用异步截图API
binding.wvContent.captureBitmapAsync(webView.width, webView.height) { bitmap -> // 处理截图结果 }
4. 优化DrawingCache截图逻辑
依赖WebView的DrawingCache,确保渲染完成后再生成缓存:
fun screenshotWithCache(webView: WebView): Bitmap? { return try { webView.setDrawingCacheEnabled(true) webView.drawingCacheQuality = View.DRAWING_CACHE_QUALITY_HIGH // 先清理旧缓存 webView.destroyDrawingCache() // 重新构建缓存 webView.buildDrawingCache() // 复制缓存生成Bitmap Bitmap.createBitmap(webView.drawingCache).also { // 用完清理缓存 webView.destroyDrawingCache() webView.setDrawingCacheEnabled(false) } } catch (e: Exception) { e.printStackTrace() null } }
内容的提问来源于stack exchange,提问作者imsunburnt
相关产品推荐
相关产品推荐

