- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想将 HTML fragment 渲染到 WebView,然后获取它的位图。这是一个代码 fragment (位于 MainActivity.onCreate 内部):
final WebView view = new WebView(this);
String summary = "<html><body>You scored <b>192</b> points.</body></html>";
view.loadData(summary, "text/html", null);
Bitmap bitmap= Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);
Canvas offscreen = new Canvas(bitmap);
view.draw(offscreen);
最初创建'位图'时,它是透明的。在“view.draw”调用期间,它提供了全白背景,但未呈现 HTML 摘要字符串!
通过以下方式获得完全相同的效果:
final WebView view = new WebView(this);
String summary = "<html><body>You scored <b>192</b> points.</body></html>";
view.loadData(summary, "text/html", null);
Picture picture = new Picture();
Canvas picCanvas = picture.beginRecording(400, 400);
view.draw(picCanvas);
picture.endRecording();
Bitmap bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);
Canvas offscreen = new Canvas(bitmap);
offscreen.drawPicture(picture);
在这两种情况下,底层位图都被修改为显示全白背景,但仅此而已。任何人都可以阐明为什么会这样吗?如果这很重要,我使用的是运行 Android 6.0.1 API 23 的 Sony Experia Z3。
最佳答案
我花了一段时间才弄明白这一点,但现在就开始吧。问题是/是 WebView.loadData() 和 WebView.loadURL() 是非阻塞的——它们自己不执行任何工作,而是将 Runnable 发布到当前 Activity (即 UI 线程),当执行后,将实际加载并呈现 HTML。因此,正如我在上面所做的那样,将 WebView.loadData() 调用放在 Activity.onCreae() 中永远无法工作,因为 loadData() 的实际工作在 onCreate() 退出之前不会发生;因此是空白图像。
这是建议的解决方案,在主 Application 对象的子类中实现。这是在互联网上跋涉并尝试自己的想法的累积结果:
public Bitmap renderHtml(final String html, int containerWidthDp, int containerHeightDp) {
final int containerWidthPx = dpToPx(containerWidthDp);
final int containerHeightPx = dpToPx(containerHeightDp);
final Bitmap bitmap = Bitmap.createBitmap(containerWidthPx, containerHeightPx, Bitmap.Config.ARGB_8888);
final CountDownLatch signal = new CountDownLatch(1);
final AtomicBoolean ready = new AtomicBoolean(false);
final Runnable renderer = new Runnable() {
@Override
public void run() {
final WebView webView = new WebView(getPane());
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView v, int newProgress) {
super.onProgressChanged(v, newProgress);
if (newProgress==100) {
ready.set(true);
}
}
});
webView.setPictureListener(new WebView.PictureListener() {
@Override
public void onNewPicture(WebView v, Picture picture) {
if (ready.get()) {
final Canvas c = new Canvas(bitmap);
v.draw(c);
v.setPictureListener(null);
signal.countDown();
}
}
});
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView v, String url) {
super.onPageFinished(v, url);
ready.set(true);
}
});
webView.layout(0, 0, containerWidthPx, containerHeightPx);
/* The next statement will cause a new task to be queued up
behind this one on the UI thread. This new task shall
trigger onNewPicture(), and only then shall we release
the lock. */
webView.loadData(html, "text/html; charset=utf-8", null);
}
};
runOnUiThread(renderer);
try {
signal.await(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
}
return bitmap;
}
其中“this”返回 Application 子类对象,getPane() 返回当前执行的 Activity。请注意,该例程不得在 UI 线程中执行(否则我们会遇到与上述相同的死锁)。这里的主要见解是使用锁来等待 (1) 包含 loadData() 调用的 runOnUIThread Runnable 完成,然后 (2) 由 loadData() 调用生成的 Runnable 也完成(这是 onNewPicture () 钩子(Hook)被调用)。在 onNewPicture() 中,我们将完成的图片渲染到位图上,然后释放锁以便继续执行。
我发现这个实现是“可靠的”,因为大多数时候都会返回正确呈现的位图。我仍然不完全理解 loadData/loadURL 触发了哪些事件;这似乎没有任何一致性。无论如何,signal.await() 调用有 1 秒的超时,以保证前进的进程。
关于Android WebView 离屏/位图渲染问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41273812/
如何从 Android-Native-Screen 打开 flutter 屏幕? 我开了一个 Android-Native-Screen 从现有我们 flutter 项目 . 所以,在 Android
有人知道如何使用 java 和 google chrome 最大化 selenium webdriver 窗口吗? 我已经尝试过一些命令,例如maximize () window (),但没有成功。
Redmi A65 智能电视今天正式开卖,4K 超高清大屏 + 立体声扬声器,到手价 2599 元。 IT之家了解到,Redmi A65 智能电视搭载了一块 65 英寸 4K 屏,支持 HDR
9 月 26 日消息小米电视大师「至尊纪念版」将在 9 月 29 日发布,根据今天小米集团大家电部总经理李肖爽放出的海报显示,小米电视大师至尊版有两款。 小米电视大师「至尊纪念版」是小米首款
华为手环 6 今日在海外正式发布,英文名 Band 6。这款产品是华为手环 4 的升级版,屏幕尺寸由 0.96 英寸升级为 1.47 英寸 AMOLED 屏,分辨率 194 x 368。该手环外形类
我是一名优秀的程序员,十分优秀!