我在WebView关闭屏幕上渲染了一些非常简单的HTML(只是一些文本和一个小图像)(未设置为活动的内容视图),因此我可以根据内容创建一个位图。
了解内容何时完全呈现的方法我基于此answer:
final AtomicBoolean rendered = new AtomicBoolean(false);
final WebView view = new WebView(this) {
@Override
public void invalidate() {
if (getProgress() == 100 && getContentHeight() > 0) {
if (! rendered.get()) {
rendered.set(true);
// Content should be fully rendered
}
}
super.invalidate();
}
};
// Load and lay out content
view.loadUrl(url);
view.setInitialScale(100);
view.layout(0, 0, 240, 420);
我已经在4.1.2,4.2.2,4.4.2和5.0上成功测试了这一点。但是对于4.0.3,似乎永远不会调用invalidate()
。
在尝试各种各样的事情时,我发现显示Toast并对invalidate()
进行延迟(1秒)调用可以解决问题:
@Override
public void onPageFinished(final WebView view, final String url) {
Toast.makeText(MainActivity.this, "Page loaded", Toast.LENGTH_SHORT).show();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (! rendered.get()) {
view.invalidate();
}
}
}, 1000);
}
当然,我不认为这是一个有效的解决方案,但是对invalidate()
的延迟调用对我来说是有道理的,我真的很想知道Toast的副作用是什么。是否会造成一些损坏导致重绘或类似的东西?
答案 0 :(得分:1)
很抱歉,我不能帮助你,因为我想对你做同样的操作(从离线webview控件获取屏幕截图)但在我的情况下,我无法在webview离线之前收到invalidate()事件。如果我通过插入主窗口设置为可见,则会生成invalidate(),但是在脱机(不可见)的情况下,不会生成invalidate()调用。您为获得此类结果而开发的代码只是您在此处发布的代码段,或者还有一些额外的功能可以让webview在离线模式下处于“活动状态”吗?
关于您的问题我可以建议覆盖其他invalidate()定义,如:
public void invalidate(Rect dirty)
public void invalidate(int l, int t, int r, int b)
因为在我的测试中我注意到这些最后一次被称为。
谢谢
答案 1 :(得分:0)
经过对不同(虚拟)设备的大量测试后,这是迄今为止对我来说可靠的方式。请注意,我原始问题中提到的4.0.3的“hack”仍然适用,但不包含在此处。
覆盖invalidate()
并未证明在所有测试版本上始终可靠,因此我使用PictureListener.onNewPicture(WebView view, Picture picture)
即使它已被弃用。
在我的活动中:
final WebView view = new WebView(this);
// Zooming in can improve font quality
final float scale = 2.0;
// Unfortunately, there is no method view.getContentWidth()
final int contentWidth = 240;
view.setPictureListener(new PictureListener() {
@Override
public void onNewPicture(final WebView view, final Picture picture) {
if (view.getProgress() == 100 && view.getContentHeight() > 0) {
view.setPictureListener(null);
// Content is now fully rendered
final int width = Math.round(contentWidth * scale);
final int height = Math.round(view.getContentHeight() * scale);
final Bitmap bitmap = getBitmap(view, width, height);
// Display or print bitmap...
}
}
});
view.loadUrl(url);
view.setInitialScale(Math.round(scale * 100));
// Width and height must be at least 1
view.layout(0, 0, 1, 1);
getBitmap()
方法:
private Bitmap getBitmap(
final WebView view, final int width, final int height) {
final Bitmap bitmap = Bitmap.createBitmap(
width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
这是我能提供的最好的。该应用程序尚未经过广泛测试,但到目前为止,它始终无法正确呈现包含小型GIF图像的小文档。
答案 2 :(得分:0)
感谢您的建议。我可以确认PictureListener方式是否仍然工作,如果depecrated(测试到Android 5版本),因为如果我发现的第一个解决方案。不幸的是,这个听众有一个问题,在每个建议之间引入延迟,这意味着你没有立即建议变化。如果在你的情况下这不是一个问题,那么听众解决方案对你来说没问题,但在我的情况下,我需要被建议"立即了解页面中的任何更改,以获取更新的屏幕截图。