Android Webview:在渲染完成时检测
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21000566/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android Webview: Detect when rendering is finished
提问by lolyoshi
I want to snapshot the WebView after the WebView is loaded. However, the returned bitmap is always null because the render hasn't loaded completed even though I use onPageFinished
.
I search on Internet and people suggest to use WebView.PictureListener
, but this function is deprecated in API 12.
我想在加载 WebView 后对 WebView 进行快照。但是,返回的位图始终为空,因为即使我使用onPageFinished
. 我在 Internet 上搜索,人们建议使用WebView.PictureListener
,但此功能在 API 12 中已弃用。
Some codes
一些代码
public class MainActivity extends Activity {
private WebView mButterflyWebView;
/**
* Gets html content from the assets folder.
*/
private String getHtmlFromAsset() {
InputStream is;
StringBuilder builder = new StringBuilder();
String htmlString = null;
try {
is = getAssets().open(getString(R.string.butterfly_html));
if (is != null) {
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
htmlString = builder.toString();
}
} catch (IOException e) {
e.printStackTrace();
}
return htmlString;
}
/**
* Initializes views, controls...
*/
private void init() {
mButterflyWebView = (WebView) findViewById(R.id.butterfly_webview);
mButterflyWebView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress == 100){
if (capturePictureWebView() != null){
saveBitmapToFile(capturePictureWebView());
}
}
}
});
}
/**
* Loads html page with the content.
*/
private void loadHtmlPage() {
String htmlString = getHtmlFromAsset();
if (htmlString != null)
mButterflyWebView.loadDataWithBaseURL(
"file:///android_asset/images/", htmlString, "text/html",
"UTF-8", null);
else
Toast.makeText(this, R.string.no_such_page, Toast.LENGTH_LONG)
.show();
}
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
loadHtmlPage();
}
private Bitmap capturePictureWebView() {
mButterflyWebView.measure(MeasureSpec.makeMeasureSpec(
MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
mButterflyWebView.layout(0, 0, mButterflyWebView.getMeasuredWidth(),
mButterflyWebView.getMeasuredHeight());
mButterflyWebView.setDrawingCacheEnabled(true);
mButterflyWebView.buildDrawingCache();
if (mButterflyWebView.getMeasuredWidth() == 0 || mButterflyWebView.getMeasuredHeight() == 0){
return null;
}
Bitmap bm = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888);
System.out.println("width=" + mButterflyWebView.getMeasuredWidth());
System.out.println("height=" + mButterflyWebView.getMeasuredHeight());
Canvas bigcanvas = new Canvas(bm);
// bigcanvas.scale(720/mButterflyWebView.getMeasuredWidth(), 1280/mButterflyWebView.getMeasuredHeight());
Paint paint = new Paint();
int iHeight = bm.getHeight();
bigcanvas.drawBitmap(bm, 0, iHeight, paint);
mButterflyWebView.draw(bigcanvas);
return bm;
}
private void saveBitmapToFile(Bitmap bitmap) {
try {
FileOutputStream out = new FileOutputStream("/storage/sdcard0/a.png");
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
采纳答案by lolyoshi
Finally I got the very detailed for this problem. This explains why it always returns null bitmap.
最后我得到了这个问题的非常详细的信息。这解释了为什么它总是返回空位图。
Every change in my app are triggered by a user action so I came up with a modified version that only trigger invalidate() after a touchEvent
我的应用程序中的每个更改都是由用户操作触发的,因此我想出了一个修改版本,该版本仅在 touchEvent 之后触发 invalidate()
Thank for all your help.
感谢您的帮助。
回答by Andros
You should try to use a WebChromeClient
and implement onProgressChanged
:
您应该尝试使用 aWebChromeClient
并实现onProgressChanged
:
mButterflyWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int progress) {
if (progress == 100) {
// do screenshot
}
}
});
EDIT: to check if onPageStarted is loaded more than once :
编辑:检查 onPageStarted 是否加载不止一次:
mButterflyWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.d("WebView", "onPageStarted " + url);
}
@Override
public void onPageFinished(WebView view, String url) {
Log.d("WebView", "onPageFinished " + url);
}
});
回答by Daniel Novak
The best way to detect if a page has rendered is to use the onPageCommitVisiblecallback, available from API 23. onPageLoadFinished
is not suitable, since it's delivered too soon (when the HTML is processed, but not yet rendered).
检测页面是否已呈现的最佳方法是使用API 23 提供的onPageCommitVisible回调。onPageLoadFinished
不合适,因为它交付得太快(处理 HTML 但尚未呈现时)。
webview.setWebViewClient(new WebViewClient() {
webview.setWebViewClient(new WebViewClient() {
@Override
public void onPageCommitVisible (WebView view,
String url)
}
}
}
回答by Frank
You can do it like this, in your WebView:
你可以在你的 WebView 中这样做:
@Override
public void invalidate() {
super.invalidate();
if (getContentHeight() > 0) {
// WebView has displayed some content and is scrollable.
}
}
Thanks to: https://stackoverflow.com/a/14678910/1310343
回答by shreedhar
The renderer will not finish rendering when the OnPageFinshed method is called or the progress reaches 100% so both methods don't guarantee you that the view was completely rendered.
当调用 OnPageFinshed 方法或进度达到 100% 时,渲染器将不会完成渲染,因此这两种方法都不能保证视图已完全渲染。
But you can figure out from OnLoadResource method what has been already rendered and what is still rendering. And this method gets called several times.
但是您可以从 OnLoadResource 方法中找出已经呈现的内容以及仍在呈现的内容。这个方法被多次调用。
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
// Log and see all the urls and know exactly what is being rendered and visible. If you wanna know when the entire page is completely rendered, find the last url from log and check it with if clause and implement your logic there.
if (url.contains("assets/loginpage/img/ui/forms/")) {
// loginpage is rendered and visible now.
// your logic here.
}
}
回答by Martin
private class CfdWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.v(TAG, "shouldOverrideUrlLoading: " + url);;
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Log.v(TAG, "onPageFinished: " + url);
// do something
}
}