Draw WebView into a Canvas in Android-L

2020-02-05 05:19发布

I'm using Android Print Framework to save the HTML Content of the WebView as PDF. Since WebView in Android-L has a new approach to render the WebView content, it is advised to Call enableSlowWholeDocumentDraw() method before creating any webviews. This will disable rendering optimization so WebView will be able to render the whole HTML page.

Here is the part of the Code to Draw WebView into a Canvas.

PdfDocument.Page page = document.startPage(pageInfo);
mWebView.draw(page.getCanvas());

I tried calling WebView.enableSlowWholeDocumentDraw() from Application, BaseActivity and also right after and before Creating WebView inside my Fragment. But this didn't help.

I tried enabling/disabling Hardware Acceleration by setting the Layer Type as SOFTWARE and HARDWARE but this didn't help as well. I still cannot draw the whole WebView. Only the Visible portion will be drawn to the Canvas.

Has anybody noticed this behaviour ? Is there a solution for that or is this a Bug ?

EDIT

It turns out that it's not about WebView.enableSlowWholeDocumentDraw() and we are still discussing about the issue. This is the Bug Report. And here is the Sample App to reproduce the issue.

4条回答
Evening l夕情丶
2楼-- · 2020-02-05 05:27

Struggled with this/similar issue myself for ages. Finally found a solution, for some reason webView.draw(page.getCanvas()) renders the whole content with KitKat but not with Lollipop (even with enableSlowWholeDocumentDraw()).
However, using (webView.capturePicture()).draw(page.getCanvas()) in combination with enableSlowWholeDocumentDraw() DOES work for Lollipop, although capturePicture() is deprecated.
A final potentially important point to note is that typically you see many calls to "onDraw" as a webView loads its data and I found that with Lollipop my snapshot was getting taken prematurely (before the content had been fully loaded - annoyingly even the onPageFinished() callback method of webViewClient does not guarantee this!) - my solution was to have a custom webView and in the onDraw method, add this as the FIRST LINE: if(this.getContentHeight() == 0) return; i.e. don't bother to do any drawing unless there is some proper content. That way you should never get a blank page snapshot - although from your description it sounds like this might not be impacting you....

查看更多
地球回转人心会变
3楼-- · 2020-02-05 05:34

You need to call WebView.enableSlowWholeDocumentDraw() before creating any WebViews in your app.

That is, if you have a WebView somewhere in your static layout, make sure you call WebView.enableSlowWholeDocumentDraw() before your first call to setContentView() that inflates a layout with WebView.

Also make sure that your WebView is indeed big. For example, if its layout size is set to match_parent, then your WebView will have the size of the screen, and this is what will be captured. You need to set some artificially high values for width and height. This question contains a nice illustration for that: WebView.draw() not properly working on latest Android System WebView Update

查看更多
爱情/是我丢掉的垃圾
4楼-- · 2020-02-05 05:39

I am the author of this question.

To fix this problem, I had to call WebView.enableSlowWholeDocumentDraw() before inflating the view in your fragment. In the comments of Mikhail Naganov's answer, I saw that you tried a lot of options but not this one. Below is the code that I use in the onCreateView() method of your fragment with the WebView.

public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle bundle){
    //Enable the drawing of the whole document for Lollipop to get the whole WebView
    if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){
        WebView.enableSlowWholeDocumentDraw();
    }
    View view = inflater.inflate(R.layout.my_layout, parent, false);

   /* Rest of code */
}

There's really nothing else to it. If that doesn't work, then it might be a bug and you should report as Mikhail had suggested.

Hope this helps !

查看更多
女痞
5楼-- · 2020-02-05 05:39
if(Build.VERSION.SDK_INT>=21)    {
    WebView.enableSlowWholeDocumentDraw();
}

public void capture(WebView webView) {
    WebView lObjWebView = webView;
    lObjWebView.measure(MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    lObjWebView.layout(0, 0, lObjWebView.getMeasuredWidth(), lObjWebView.getMeasuredHeight());
    Bitmap bm = Bitmap.createBitmap(lObjWebView.getMeasuredWidth(), lObjWebView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);

    Canvas bigcanvas = new Canvas(bm);
    Paint paint = new Paint();
    int iHeight = bm.getHeight();
    bigcanvas.drawBitmap(bm, 0, iHeight, paint);
    lObjWebView.draw(bigcanvas);

    if (bm != null) {
        try {
            File dir = new File(Environment.getExternalStorageDirectory() + "/" + "folder");

            Calendar lObjCalendar = Calendar.getInstance();

            int hour = lObjCalendar.get(Calendar.HOUR);
            int min = lObjCalendar.get(Calendar.MINUTE);
            int sec = lObjCalendar.get(Calendar.SECOND);
            int mili = lObjCalendar.get(Calendar.MILLISECOND);
            int day = lObjCalendar.get(Calendar.DAY_OF_YEAR);
            int month = lObjCalendar.get(Calendar.MONTH);
            int year = lObjCalendar.get(Calendar.YEAR);

            String realDate = "ERS_" + day + month + year + "_" + hour + min + sec + mili;

            if (dir.exists()) {
                OutputStream fOut = null;
                File file = new File(dir, realDate + ".jpg");
                fOut = new FileOutputStream(file);

                bm.compress(Bitmap.CompressFormat.PNG, 50, fOut);
                fOut.flush();
                fOut.close();
                bm.recycle();
            }
            else {

                if (dir.mkdir()) {
                    OutputStream fOut = null;
                    File file = new File(dir, realDate + ".jpg");
                    fOut = new FileOutputStream(file);

                    bm.compress(Bitmap.CompressFormat.PNG, 50, fOut);
                    fOut.flush();
                    fOut.close();
                    bm.recycle();
                }
                else {
                    ProjectUtil.showToast(WebPayment.this, "Problem in saving webview in external storage");
                }
            }
        }
        catch (FileNotFoundException e) {
            ProjectUtil.showToast(WebPayment.this, "Problem in saving webview in external storage");
        }
        catch (IOException e) {
            ProjectUtil.showToast(WebPayment.this, "Problem in saving webview in external storage");
        }
        catch (Exception e) {
            ProjectUtil.showToast(WebPayment.this, "Problem in saving webview in external storage");
        }
    }
}
查看更多
登录 后发表回答