WebViewが読み込まれた後にWebViewのスナップショットを作成したいのですが。ただし、onPageFinished
を使用してもレンダリングが完了していないため、返されるビットマップは常にnullです。私はインターネットで検索し、人々はWebView.PictureListener
、ただしこの関数はAPI 12で非推奨。
一部のコード
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();
}
}
}
最後に、この問題について非常に詳細に説明しました。これは、常にnullビットマップを返す理由を説明しています。
アプリのすべての変更はユーザーアクションによってトリガーされるため、touchEventの後でのみinvalidate()をトリガーする変更バージョンを思いつきました
ご協力ありがとうございます。
Android WebViewが空白/白でレンダリングされ、CSSの変更またはHTMLの変更でビューが更新されない、アニメーションが途切れる
WebChromeClient
を使用してonProgressChanged
を実装する必要があります。
mButterflyWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int progress) {
if (progress == 100) {
// do screenshot
}
}
});
[〜#〜] edit [〜#〜]: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);
}
});
ページがレンダリングされたかどうかを検出する最良の方法は、API 23から利用可能な onPageCommitVisible コールバックを使用することです。onPageLoadFinished
は配信が早すぎるため(HTMLが処理されるときに) 、まだレンダリングされていません)。
webview.setWebViewClient(new WebViewClient(){
@Override
public void onPageCommitVisible (WebView view,
String url)
}
}
あなたのWebViewでこれを行うことができます:
@Override
public void invalidate() {
super.invalidate();
if (getContentHeight() > 0) {
// WebView has displayed some content and is scrollable.
}
}
OnPageFinshedメソッドが呼び出されたとき、または進行状況が100%に達したときにレンダラーはレンダリングを完了しないため、両方のメソッドはビューが完全にレンダリングされたことを保証しません。
しかし、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.
}
}