scrollTo()之后的Android WebView损坏图形
我正在编写一个应用程序,我需要一个WebView作为Android服务的web渲染机制。 因此WebView永远不会附加到窗口。 但是,通过手动测量和布局视图(视图组),然后在其上绘制位图,我可以生成页面的快照,而无需将其放入视图层次结构中 问题是,一旦我调用它来scrollTo(),视图就不会绘制隐藏在滚动之前的页面部分并对其进行裁剪,类似这样scrollTo()之后的Android WebView损坏图形,android,scroll,webview,bitmap,draw,Android,Scroll,Webview,Bitmap,Draw,我正在编写一个应用程序,我需要一个WebView作为Android服务的web渲染机制。 因此WebView永远不会附加到窗口。 但是,通过手动测量和布局视图(视图组),然后在其上绘制位图,我可以生成页面的快照,而无需将其放入视图层次结构中 问题是,一旦我调用它来scrollTo(),视图就不会绘制隐藏在滚动之前的页面部分并对其进行裁剪,类似这样 layout(mWebView, maxWidth, maxHeight); // page is loaded mWebView.scrollTo(
layout(mWebView, maxWidth, maxHeight);
// page is loaded
mWebView.scrollTo(...);
// here I've tried number of things like mWebView.invalidate(), mWebView.requestLayout() or mWebView.refreshDrawableState()
final Bitmap bitmap = capture(mWebView);
WebView在使用以下方法请求页面加载之前很久就被布置好了
private void layout(
@NonNull final WebView webView, final int targetWidth, final int targetHeight) {
webView.measure(
View.MeasureSpec.makeMeasureSpec(targetWidth, View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(targetHeight, View.MeasureSpec.AT_MOST));
webView.layout(0, 0, targetWidth, targetHeight);
}
位图是使用以下代码捕获的
private Bitmap capture(
@NonNull final WebView webView) {
webView.setDrawingCacheEnabled(true);
webView.buildDrawingCache();
final Bitmap bitmap = Bitmap.createBitmap(
webView.getWidth(), webView.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
webView.draw(canvas);
webView.setDrawingCacheEnabled(false);
return bitmap;
}
整个过程是这样的
layout(mWebView, maxWidth, maxHeight);
// page is loaded
mWebView.scrollTo(...);
// here I've tried number of things like mWebView.invalidate(), mWebView.requestLayout() or mWebView.refreshDrawableState()
final Bitmap bitmap = capture(mWebView);
重要提示:当我在Web视图中加载页面时,该页面通常连接到活动中的窗口,Web视图会滚动到我想要的位置,页面会很好地显示出来
有什么区别?这与android将WebView附加到活动窗口时对WebView所做的操作有何不同
mWebView.scrollTo(...);
webView.setDrawingCacheEnabled(true);
webView.buildDrawingCache();//write these lines before posting the capture event
new Handler.post(){
new Runnable(){
public void run(){
final Bitmap bitmap = capture(mWebView);
}
}
}
它可能会解决您的问题…:-) 我终于找到了这个问题的根本原因。 我创建位图的机制依赖于WebView启用了图形缓存并在画布上绘制自己这一事实 图形缓存将被启用,但在滚动更改后从未更新,因为只有视图状态更改 看起来,由于我正在为视图渲染启用硬件加速,所以我需要做的就是启用图形缓存,并在设置滚动位置后,在需要新位图时使用它(我甚至不需要为此目的使视图无效) 因此,解决方案如下:
public void init() {
mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mWebView.setDrawingCacheEnabled(true);
// (layout the view)
}
public void capture(...) {
mWebView.scrollTo(...);
final Bitmap capturedBitmap = mWebView.getDrawingCache();
// do sth with the bitmap
// ...
}
因此,这一切都要简单得多。我确信
WebView
采用了优化,如果它检测到自己没有连接到窗口,就不会重新绘制自己。您是否尝试在WebView上调用invalidate()
?也许这会迫使你重新画一张完整的图……谢谢你的回复。是的,我有。我尝试过requestLayout(),也尝试过在页面加载后的短时间(~1s)超时后执行此操作。我已经看过了,很难准确理解那里发生了什么(WebView、WebViewChromium等),但我可以告诉您,某些绘图/滚动功能要求WebView在UI线程上运行/连接到视图层次结构。此外,类似于View.invalidate()
这适用于常规情况。当我只调整webview滚动位置时,它不起作用。感谢回复,但这没有帮助。